All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] perf: persistent events prototype
@ 2010-05-22 19:00 Borislav Petkov
  2010-05-22 19:00 ` [PATCH 2/2] x86, mce: Make MCE tracepoint persistent event Borislav Petkov
                   ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-05-22 19:00 UTC (permalink / raw)
  To: Ingo Molnar, Frederic Weisbecker, Steven Rostedt, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Lin Ming
  Cc: linux-kernel, Borislav Petkov

Hi,

here is my first stab at persistent events. And since it is a first one,
there's no special tricks but simply all subsystems which init before
perf and have declared static tracepoints, simply mark some of them as
persistent and perf enables them when inits.

I haven't tested this yet and will do so when I get to work next week
but I'm sending it out now so that I can get your thoughts on this and
whether this is an agreeable direction I'm taking.

Couple of yet unresolved issues I see with this:

* persistent events are enabled unconditionally on all cpus and while
this makes sense for MCEs tracing, do we still want to be flexible here
and supply a cpumask instead?

* what happens if there's no consumer for the traced data, the easiest
would be to do nothing and let it get truncated in the trace buffer with
newer data overwriting the oldest sample?

* what about other events, and most importantly, what about hw events
for which we take a PMU and want to make them persistent at the
same time and it so happens that after making a couple of events
persistent, we run out of PMUs and make the perf tool almost useless
since persistent events are hogging all the hardware resources?

* btw, perf and ftrace really need to get married :)

/me ducks now...

Thanks.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 2/2] x86, mce: Make MCE tracepoint persistent event
  2010-05-22 19:00 [RFC PATCH 0/2] perf: persistent events prototype Borislav Petkov
@ 2010-05-22 19:00 ` Borislav Petkov
       [not found] ` <1274554806-28216-2-git-send-email-bp@alien8.de>
  2010-05-23 20:36 ` [RFC PATCH 0/2] perf: persistent events prototype Steven Rostedt
  2 siblings, 0 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-05-22 19:00 UTC (permalink / raw)
  To: Ingo Molnar, Frederic Weisbecker, Steven Rostedt, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Lin Ming
  Cc: linux-kernel, Borislav Petkov

Not-yet-signed-off-by: Borislav Petkov <bp@alien8.de>
---
 arch/x86/kernel/cpu/mcheck/mce.c |    4 ++++
 include/trace/events/mce.h       |    1 +
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 8a6f0af..5f40726 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1668,6 +1668,10 @@ int __init mcheck_init(void)
 
 	mcheck_intel_therm_init();
 
+#ifdef CONFIG_EVENT_TRACING
+	event_mce_record.type = EVENT_PERSISTENT;
+#endif
+
 	return 0;
 }
 
diff --git a/include/trace/events/mce.h b/include/trace/events/mce.h
index 7eee778..b1ad772 100644
--- a/include/trace/events/mce.h
+++ b/include/trace/events/mce.h
@@ -5,6 +5,7 @@
 #define _TRACE_MCE_H
 
 #include <linux/ktime.h>
+#include <linux/ftrace_event.h>
 #include <linux/tracepoint.h>
 #include <asm/mce.h>
 
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
       [not found] ` <1274554806-28216-2-git-send-email-bp@alien8.de>
@ 2010-05-23 18:15   ` Peter Zijlstra
  2010-05-23 18:33     ` Borislav Petkov
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Zijlstra @ 2010-05-23 18:15 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

On Sat, 2010-05-22 at 21:00 +0200, Borislav Petkov wrote:
> Register and enable events marked as persistent right after perf events
> has initialized.
> 
> Not-yet-signed-off-by: Borislav Petkov <bp@alien8.de>

Nah, this is totally wrong.

A persistent event would simply be a regular event, but created by the
kernel and not tied to a file-desc's lifetime.




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-23 18:15   ` [PATCH 1/2] perf: Add persistent events Peter Zijlstra
@ 2010-05-23 18:33     ` Borislav Petkov
  2010-05-23 18:40       ` Peter Zijlstra
  0 siblings, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-05-23 18:33 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

From: Peter Zijlstra <peterz@infradead.org>
Date: Sun, May 23, 2010 at 08:15:13PM +0200

> On Sat, 2010-05-22 at 21:00 +0200, Borislav Petkov wrote:
> > Register and enable events marked as persistent right after perf events
> > has initialized.
> > 
> > Not-yet-signed-off-by: Borislav Petkov <bp@alien8.de>
> 
> Nah, this is totally wrong.
> 
> A persistent event would simply be a regular event, but created by the
> kernel and not tied to a file-desc's lifetime.

So you're saying the trace_mce_record() tracepoint for example should
be created completely internally in the kernel and cease to be a
tracepoint? Will it still be able to be selected by perf -e?

Please elaborate.

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-23 18:33     ` Borislav Petkov
@ 2010-05-23 18:40       ` Peter Zijlstra
  2010-05-23 18:54         ` Borislav Petkov
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Zijlstra @ 2010-05-23 18:40 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

On Sun, 2010-05-23 at 20:33 +0200, Borislav Petkov wrote:
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Sun, May 23, 2010 at 08:15:13PM +0200
> 
> > On Sat, 2010-05-22 at 21:00 +0200, Borislav Petkov wrote:
> > > Register and enable events marked as persistent right after perf events
> > > has initialized.
> > > 
> > > Not-yet-signed-off-by: Borislav Petkov <bp@alien8.de>
> > 
> > Nah, this is totally wrong.
> > 
> > A persistent event would simply be a regular event, but created by the
> > kernel and not tied to a file-desc's lifetime.
> 
> So you're saying the trace_mce_record() tracepoint for example should
> be created completely internally in the kernel and cease to be a
> tracepoint? Will it still be able to be selected by perf -e?

No, it should be a regular tracepoint as far as tracepoints are
concerned.

But the only thing persistence should add is an instance of a
perf_event, it should not modify either the perf_event nor the
tracepoint code.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-23 18:40       ` Peter Zijlstra
@ 2010-05-23 18:54         ` Borislav Petkov
  2010-05-23 19:23           ` Peter Zijlstra
  0 siblings, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-05-23 18:54 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

From: Peter Zijlstra <peterz@infradead.org>
Date: Sun, May 23, 2010 at 08:40:47PM +0200

> > > A persistent event would simply be a regular event, but created by the
> > > kernel and not tied to a file-desc's lifetime.
> > 
> > So you're saying the trace_mce_record() tracepoint for example should
> > be created completely internally in the kernel and cease to be a
> > tracepoint? Will it still be able to be selected by perf -e?
> 
> No, it should be a regular tracepoint as far as tracepoints are
> concerned.
> 
> But the only thing persistence should add is an instance of a
> perf_event, it should not modify either the perf_event nor the
> tracepoint code.

which means that subsystems which initialize earlier than perf (mce,
for example) should have to be notified when perf is ready so that they
could register a persistent event. How does that sound?

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-23 18:54         ` Borislav Petkov
@ 2010-05-23 19:23           ` Peter Zijlstra
  2010-05-25  7:32             ` Borislav Petkov
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Zijlstra @ 2010-05-23 19:23 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

On Sun, 2010-05-23 at 20:54 +0200, Borislav Petkov wrote:
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Sun, May 23, 2010 at 08:40:47PM +0200
> 
> > > > A persistent event would simply be a regular event, but created by the
> > > > kernel and not tied to a file-desc's lifetime.
> > > 
> > > So you're saying the trace_mce_record() tracepoint for example should
> > > be created completely internally in the kernel and cease to be a
> > > tracepoint? Will it still be able to be selected by perf -e?
> > 
> > No, it should be a regular tracepoint as far as tracepoints are
> > concerned.
> > 
> > But the only thing persistence should add is an instance of a
> > perf_event, it should not modify either the perf_event nor the
> > tracepoint code.
> 
> which means that subsystems which initialize earlier than perf (mce,
> for example) should have to be notified when perf is ready so that they
> could register a persistent event. How does that sound?

Either we add some notifier thing, or we simply add an explicit call in
the init sequence after the perf_event subsystem is running. I would
suggest we start with some explicit call, and take it from there.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [RFC PATCH 0/2] perf: persistent events prototype
  2010-05-22 19:00 [RFC PATCH 0/2] perf: persistent events prototype Borislav Petkov
  2010-05-22 19:00 ` [PATCH 2/2] x86, mce: Make MCE tracepoint persistent event Borislav Petkov
       [not found] ` <1274554806-28216-2-git-send-email-bp@alien8.de>
@ 2010-05-23 20:36 ` Steven Rostedt
  2 siblings, 0 replies; 31+ messages in thread
From: Steven Rostedt @ 2010-05-23 20:36 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Frederic Weisbecker, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

On Sat, 2010-05-22 at 21:00 +0200, Borislav Petkov wrote:

> * btw, perf and ftrace really need to get married :)

We all agree to that. It's the wedding plans the in-laws are fighting
over.

-- Steve



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-23 19:23           ` Peter Zijlstra
@ 2010-05-25  7:32             ` Borislav Petkov
  2010-05-25 14:59               ` Peter Zijlstra
  0 siblings, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-05-25  7:32 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

From: Peter Zijlstra <peterz@infradead.org>
Date: Sun, May 23, 2010 at 09:23:21PM +0200

> Either we add some notifier thing, or we simply add an explicit call in
> the init sequence after the perf_event subsystem is running. I would
> suggest we start with some explicit call, and take it from there.

Ok, this couldn't be more straightforward. So I looked at the init
sequence we do when booting wrt to perf/ftrace initialization:

start_kernel
...
|-> sched_init
    |-> perf_event_init
...
|-> ftrace_init
rest_init
kernel_init
|-> do_pre_smp_initcalls
|...
|-> smp_int
|-> do_basic_setup
    |-> do_initcalls

and one of the convenient places after both perf is initialized and
ftrace has enumerated the tracepoints is do_initcalls() (It cannot be an
early_initcall since at that time we're not running SMP yet and we want
the MCE event per cpu.)

So I added a core_initcall that registers the mce perf event. This makes
it more or less a persistent event without any changes to the perf_event
subsystem. I guess this should work - at least it builds here, will give
it a run later.

As a further enhancement, the init-function should read out all the
logged mce events which survived the warm reboot and those which happen
between mce init and the actual event registration so that perf can
postprocess those too at a more convenient time.

Thanks.

---
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 8a6f0af..e3370a2 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -94,6 +94,7 @@ static char			*mce_helper_argv[2] = { mce_helper, NULL };
 
 static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
 static DEFINE_PER_CPU(struct mce, mces_seen);
+static DEFINE_PER_CPU(struct perf_event *, mce_event);
 static int			cpu_missing;
 
 /*
@@ -1996,6 +1997,60 @@ static void __cpuinit mce_reenable_cpu(void *h)
 	}
 }
 
+struct perf_event_attr pattr = {
+	.type	= PERF_TYPE_TRACEPOINT,
+	.size	= sizeof(pattr),
+};
+
+static int mcheck_enable_perf_event_on_cpu(int cpu)
+{
+	struct perf_event *event;
+
+	pattr.config = event_mce_record.id;
+
+	event = perf_event_create_kernel_counter(&pattr, cpu, -1, NULL);
+	if (IS_ERR(event))
+		return -EINVAL;
+
+	perf_event_enable(event);
+	per_cpu(mce_event, cpu) = event;
+
+	return 0;
+}
+
+static void mcheck_disable_perf_event_on_cpu(int cpu)
+{
+	struct perf_event *event = per_cpu(mce_event, cpu);
+
+	if (!event)
+		return;
+
+	perf_event_disable(event);
+	per_cpu(mce_event, cpu) = NULL;
+	perf_event_release_kernel(event);
+}
+
+static int mcheck_init_perf_event(void)
+{
+	int cpu, err;
+
+	get_online_cpus();
+
+	for_each_online_cpu(cpu) {
+		err = mcheck_enable_perf_event_on_cpu(cpu);
+		if (err) {
+			printk(KERN_ERR "mce: error initializing mce tracepoint"
+					" on cpu %d\n", cpu);
+			return err;
+		}
+	}
+
+	put_online_cpus();
+
+	return 0;
+}
+core_initcall(mcheck_init_perf_event);
+
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
 static int __cpuinit
 mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
@@ -2009,6 +2064,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 		mce_create_device(cpu);
 		if (threshold_cpu_callback)
 			threshold_cpu_callback(action, cpu);
+		mcheck_enable_perf_event_on_cpu(cpu);
 		break;
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
@@ -2020,6 +2076,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 	case CPU_DOWN_PREPARE_FROZEN:
 		del_timer_sync(t);
 		smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
+		mcheck_disable_perf_event_on_cpu(cpu);
 		break;
 	case CPU_DOWN_FAILED:
 	case CPU_DOWN_FAILED_FROZEN:
@@ -2029,6 +2086,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 			add_timer_on(t, cpu);
 		}
 		smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
+		mcheck_enable_perf_event_on_cpu(cpu);
 		break;
 	case CPU_POST_DEAD:
 		/* intentionally ignoring frozen here */

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-25  7:32             ` Borislav Petkov
@ 2010-05-25 14:59               ` Peter Zijlstra
  2010-05-28 14:33                 ` Ingo Molnar
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Zijlstra @ 2010-05-25 14:59 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

On Tue, 2010-05-25 at 09:32 +0200, Borislav Petkov wrote:
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Sun, May 23, 2010 at 09:23:21PM +0200
> 
> > Either we add some notifier thing, or we simply add an explicit call in
> > the init sequence after the perf_event subsystem is running. I would
> > suggest we start with some explicit call, and take it from there.
> 
> Ok, this couldn't be more straightforward. So I looked at the init
> sequence we do when booting wrt to perf/ftrace initialization:
> 
> start_kernel
> ...
> |-> sched_init
>     |-> perf_event_init
> ...
> |-> ftrace_init
> rest_init
> kernel_init
> |-> do_pre_smp_initcalls
> |...
> |-> smp_int
> |-> do_basic_setup
>     |-> do_initcalls
> 
> and one of the convenient places after both perf is initialized and
> ftrace has enumerated the tracepoints is do_initcalls() (It cannot be an
> early_initcall since at that time we're not running SMP yet and we want
> the MCE event per cpu.)
> 
> So I added a core_initcall that registers the mce perf event. This makes
> it more or less a persistent event without any changes to the perf_event
> subsystem. I guess this should work - at least it builds here, will give
> it a run later.
> 
> As a further enhancement, the init-function should read out all the
> logged mce events which survived the warm reboot and those which happen
> between mce init and the actual event registration so that perf can
> postprocess those too at a more convenient time.

Right, so that looks good. Now the interesting part is twofold:

 1) expose these perf_events to userspace, since they're now created
    in kernel, there is no user-space access point to them. One way
    way would be to extend the perf syscall to allow attaching to an
    existing instance (but that would limit us to a single instance per
    'attr'), or create some /debug or /sys iteration of all such events.


 2) get these things a buffer, perf_events as created don't actually
    have an output buffer, normally that is created at mmap() time, but
    since you cannot mmap() a kernel side event, it doesn't get to have
    a buffer. This could be done by extracting perf_mmap_data_alloc()
    into a sensible interface.



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-25 14:59               ` Peter Zijlstra
@ 2010-05-28 14:33                 ` Ingo Molnar
  2010-05-28 15:17                   ` Peter Zijlstra
  0 siblings, 1 reply; 31+ messages in thread
From: Ingo Molnar @ 2010-05-28 14:33 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Borislav Petkov, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel


* Peter Zijlstra <peterz@infradead.org> wrote:

> On Tue, 2010-05-25 at 09:32 +0200, Borislav Petkov wrote:
> > From: Peter Zijlstra <peterz@infradead.org>
> > Date: Sun, May 23, 2010 at 09:23:21PM +0200
> > 
> > > Either we add some notifier thing, or we simply add an explicit call in
> > > the init sequence after the perf_event subsystem is running. I would
> > > suggest we start with some explicit call, and take it from there.
> > 
> > Ok, this couldn't be more straightforward. So I looked at the init
> > sequence we do when booting wrt to perf/ftrace initialization:
> > 
> > start_kernel
> > ...
> > |-> sched_init
> >     |-> perf_event_init
> > ...
> > |-> ftrace_init
> > rest_init
> > kernel_init
> > |-> do_pre_smp_initcalls
> > |...
> > |-> smp_int
> > |-> do_basic_setup
> >     |-> do_initcalls
> > 
> > and one of the convenient places after both perf is initialized and
> > ftrace has enumerated the tracepoints is do_initcalls() (It cannot be an
> > early_initcall since at that time we're not running SMP yet and we want
> > the MCE event per cpu.)
> > 
> > So I added a core_initcall that registers the mce perf event. This makes
> > it more or less a persistent event without any changes to the perf_event
> > subsystem. I guess this should work - at least it builds here, will give
> > it a run later.
> > 
> > As a further enhancement, the init-function should read out all the
> > logged mce events which survived the warm reboot and those which happen
> > between mce init and the actual event registration so that perf can
> > postprocess those too at a more convenient time.
> 
> Right, so that looks good. Now the interesting part is twofold:
> 
>  1) expose these perf_events to userspace, since they're now created
>     in kernel, there is no user-space access point to them. One way
>     way would be to extend the perf syscall to allow attaching to an
>     existing instance (but that would limit us to a single instance per
>     'attr'), or create some /debug or /sys iteration of all such events.

Yeah.

>  2) get these things a buffer, perf_events as created don't actually
>     have an output buffer, normally that is created at mmap() time, but
>     since you cannot mmap() a kernel side event, it doesn't get to have
>     a buffer. This could be done by extracting perf_mmap_data_alloc()
>     into a sensible interface.

#2 could be a new syscall: sys_create_ring_buffer or so?

	Ingo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-28 14:33                 ` Ingo Molnar
@ 2010-05-28 15:17                   ` Peter Zijlstra
  2010-05-28 15:57                     ` Borislav Petkov
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Zijlstra @ 2010-05-28 15:17 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Borislav Petkov, Frederic Weisbecker, Steven Rostedt,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

On Fri, 2010-05-28 at 16:33 +0200, Ingo Molnar wrote:

> >  2) get these things a buffer, perf_events as created don't actually
> >     have an output buffer, normally that is created at mmap() time, but
> >     since you cannot mmap() a kernel side event, it doesn't get to have
> >     a buffer. This could be done by extracting perf_mmap_data_alloc()
> >     into a sensible interface.
> 
> #2 could be a new syscall: sys_create_ring_buffer or so?

No, they need a buffer in-kernel, syscalls aren't the ideal tool for
that :-)

I've got patches refactoring the whole buffer stuff to make it more a
self-contained entity.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-28 15:17                   ` Peter Zijlstra
@ 2010-05-28 15:57                     ` Borislav Petkov
  2010-05-28 18:07                       ` Peter Zijlstra
  0 siblings, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-05-28 15:57 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Borislav Petkov, Frederic Weisbecker,
	Steven Rostedt, Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

From: Peter Zijlstra <peterz@infradead.org>
Date: Fri, May 28, 2010 at 05:17:40PM +0200

> On Fri, 2010-05-28 at 16:33 +0200, Ingo Molnar wrote:
> 
> > >  2) get these things a buffer, perf_events as created don't actually
> > >     have an output buffer, normally that is created at mmap() time, but
> > >     since you cannot mmap() a kernel side event, it doesn't get to have
> > >     a buffer. This could be done by extracting perf_mmap_data_alloc()
> > >     into a sensible interface.
> > 
> > #2 could be a new syscall: sys_create_ring_buffer or so?
> 
> No, they need a buffer in-kernel, syscalls aren't the ideal tool for
> that :-)

Yeah, I need a per-cpu buffer ready at event registration/enable time,
maybe even have perf_event_create_kernel_counter() take care of that
buffer allocation with a flag or similar prior to enabling the event...

> I've got patches refactoring the whole buffer stuff to make it more a
> self-contained entity.

Can I see those when you're done so that I can base my stuff on top?

Thanks.

-- 
Regards/Gruss,
Boris.

Operating Systems Research Center
Advanced Micro Devices, Inc.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-28 15:57                     ` Borislav Petkov
@ 2010-05-28 18:07                       ` Peter Zijlstra
  2010-06-03 13:43                         ` Borislav Petkov
  0 siblings, 1 reply; 31+ messages in thread
From: Peter Zijlstra @ 2010-05-28 18:07 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Borislav Petkov, Frederic Weisbecker,
	Steven Rostedt, Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

On Fri, 2010-05-28 at 17:57 +0200, Borislav Petkov wrote:
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Fri, May 28, 2010 at 05:17:40PM +0200
> 
> > On Fri, 2010-05-28 at 16:33 +0200, Ingo Molnar wrote:
> > 
> > > >  2) get these things a buffer, perf_events as created don't actually
> > > >     have an output buffer, normally that is created at mmap() time, but
> > > >     since you cannot mmap() a kernel side event, it doesn't get to have
> > > >     a buffer. This could be done by extracting perf_mmap_data_alloc()
> > > >     into a sensible interface.
> > > 
> > > #2 could be a new syscall: sys_create_ring_buffer or so?
> > 
> > No, they need a buffer in-kernel, syscalls aren't the ideal tool for
> > that :-)
> 
> Yeah, I need a per-cpu buffer ready at event registration/enable time,
> maybe even have perf_event_create_kernel_counter() take care of that
> buffer allocation with a flag or similar prior to enabling the event...
> 
> > I've got patches refactoring the whole buffer stuff to make it more a
> > self-contained entity.
> 
> Can I see those when you're done so that I can base my stuff on top?


They can be found at:

http://programming.kicks-ass.net/sekrit/patches.tar.bz2

ignore the last 5 patches, those are random hackery.

In particular, look at:

patches/perf-fix-buffer-redirect.patch
patches/perf-buffer.patch
patches/perf-buffer-init.patch

(they won't apply separately in that order, simply push the full queue
until the last one or further)

After that you should be able to add:

  buffer = perf_buffer_alloc(nr_pages, watermark, cpu, flags);
  rcu_assign_pointer(event->buffer, buffer);

to allocate and attach a buffer to your event (do so for each cpu's MCE
event).

After that we still need a way to expose all that to userspace, but at
least the events will be complete and able to record bits ;-)




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-28 18:07                       ` Peter Zijlstra
@ 2010-06-03 13:43                         ` Borislav Petkov
  2010-06-03 17:32                           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-06-03 13:43 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, Borislav Petkov, Frederic Weisbecker,
	Steven Rostedt, Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

From: Peter Zijlstra <peterz@infradead.org>
Date: Fri, May 28, 2010 at 08:07:10PM +0200

> They can be found at:
> 
> http://programming.kicks-ass.net/sekrit/patches.tar.bz2
> 
> ignore the last 5 patches, those are random hackery.
> 
> In particular, look at:
> 
> patches/perf-fix-buffer-redirect.patch
> patches/perf-buffer.patch
> patches/perf-buffer-init.patch
> 
> (they won't apply separately in that order, simply push the full queue
> until the last one or further)
> 
> After that you should be able to add:
> 
>   buffer = perf_buffer_alloc(nr_pages, watermark, cpu, flags);
>   rcu_assign_pointer(event->buffer, buffer);
> 
> to allocate and attach a buffer to your event (do so for each cpu's MCE
> event).
> 
> After that we still need a way to expose all that to userspace, but at
> least the events will be complete and able to record bits ;-)

Yep, so far so good, the kernel side is almost done - this was the
easy part :). So recently I started looking into how the userspace
part could be done most efficiently so that, initially, the RAS daemon
doesn't suck in all of tools/perf when building and depend unnecessary
on libelf etc, and, at the same time, doesn't duplicate functionality
like util/debugfs, get_debugfs_mntpt(), parse_events() maybe later etc.

So, the best way to do this, IMHO, is if I start carving out common and
generic functionality into tools/lib/ or tools/util/ or similar so that
perf and ras can share those. And maybe later even other tools. This
could be where we host all the kernel headers stuff which are good for
userspace, i.e. those which are in tools/perf/util/include/linux/

Opinions, comments?

-- 
Regards/Gruss,
Boris.

Operating Systems Research Center
Advanced Micro Devices, Inc.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-03 13:43                         ` Borislav Petkov
@ 2010-06-03 17:32                           ` Arnaldo Carvalho de Melo
  2010-06-03 21:39                             ` Borislav Petkov
  2010-06-14 19:25                             ` Borislav Petkov
  0 siblings, 2 replies; 31+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-06-03 17:32 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Peter Zijlstra, Ingo Molnar, Borislav Petkov,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

Em Thu, Jun 03, 2010 at 03:43:01PM +0200, Borislav Petkov escreveu:
> From: Peter Zijlstra <peterz@infradead.org>
> Date: Fri, May 28, 2010 at 08:07:10PM +0200
> > to allocate and attach a buffer to your event (do so for each cpu's MCE
> > event).
> > 
> > After that we still need a way to expose all that to userspace, but at
> > least the events will be complete and able to record bits ;-)
> 
> Yep, so far so good, the kernel side is almost done - this was the
> easy part :). So recently I started looking into how the userspace
> part could be done most efficiently so that, initially, the RAS daemon
> doesn't suck in all of tools/perf when building and depend unnecessary
> on libelf etc, and, at the same time, doesn't duplicate functionality
> like util/debugfs, get_debugfs_mntpt(), parse_events() maybe later etc.
> 
> So, the best way to do this, IMHO, is if I start carving out common and
> generic functionality into tools/lib/ or tools/util/ or similar so that
> perf and ras can share those. And maybe later even other tools. This
> could be where we host all the kernel headers stuff which are good for
> userspace, i.e. those which are in tools/perf/util/include/linux/
> 
> Opinions, comments?

Right, that has to be done, I have sample code I want to put in samples/
to show how to use the symbol libraries in tools/perf/util/, will take a
stab at moving things for tools/lib/.

We'll need a top level Makefile, I guess, so that when asking to build
tools/perf, it notices that it has to build tools/lib/, etc.

Probably we'll need tools/lib/symbols/, tools/lib/trace/parser/ things
like that, I'll start with the symbols part, using a samples/ file I
already wrote.

- Arnaldo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-03 17:32                           ` Arnaldo Carvalho de Melo
@ 2010-06-03 21:39                             ` Borislav Petkov
  2010-06-14 19:25                             ` Borislav Petkov
  1 sibling, 0 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-06-03 21:39 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

From: Arnaldo Carvalho de Melo <acme@infradead.org>
Date: Thu, Jun 03, 2010 at 02:32:42PM -0300

> Em Thu, Jun 03, 2010 at 03:43:01PM +0200, Borislav Petkov escreveu:
> > From: Peter Zijlstra <peterz@infradead.org>
> > Date: Fri, May 28, 2010 at 08:07:10PM +0200
> > > to allocate and attach a buffer to your event (do so for each cpu's MCE
> > > event).
> > > 
> > > After that we still need a way to expose all that to userspace, but at
> > > least the events will be complete and able to record bits ;-)
> > 
> > Yep, so far so good, the kernel side is almost done - this was the
> > easy part :). So recently I started looking into how the userspace
> > part could be done most efficiently so that, initially, the RAS daemon
> > doesn't suck in all of tools/perf when building and depend unnecessary
> > on libelf etc, and, at the same time, doesn't duplicate functionality
> > like util/debugfs, get_debugfs_mntpt(), parse_events() maybe later etc.
> > 
> > So, the best way to do this, IMHO, is if I start carving out common and
> > generic functionality into tools/lib/ or tools/util/ or similar so that
> > perf and ras can share those. And maybe later even other tools. This
> > could be where we host all the kernel headers stuff which are good for
> > userspace, i.e. those which are in tools/perf/util/include/linux/
> > 
> > Opinions, comments?
> 
> Right, that has to be done, I have sample code I want to put in samples/
> to show how to use the symbol libraries in tools/perf/util/, will take a
> stab at moving things for tools/lib/.

Cool.

> We'll need a top level Makefile, I guess, so that when asking to build
> tools/perf, it notices that it has to build tools/lib/, etc.

Yep.

> Probably we'll need tools/lib/symbols/, tools/lib/trace/parser/ things
> like that, I'll start with the symbols part, using a samples/ file I
> already wrote.

Nice, let me know when you have something ready so that we don't
duplicate work. Also, I could give it a test run or two and all.

Thanks.

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-03 17:32                           ` Arnaldo Carvalho de Melo
  2010-06-03 21:39                             ` Borislav Petkov
@ 2010-06-14 19:25                             ` Borislav Petkov
  2010-06-14 21:01                               ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-06-14 19:25 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Peter Zijlstra, Ingo Molnar, Borislav Petkov,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

From: Arnaldo Carvalho de Melo <acme@infradead.org>
Date: Thu, Jun 03, 2010 at 02:32:42PM -0300

> Right, that has to be done, I have sample code I want to put in samples/
> to show how to use the symbol libraries in tools/perf/util/, will take a
> stab at moving things for tools/lib/.
> 
> We'll need a top level Makefile, I guess, so that when asking to build
> tools/perf, it notices that it has to build tools/lib/, etc.
> 
> Probably we'll need tools/lib/symbols/, tools/lib/trace/parser/ things
> like that, I'll start with the symbols part, using a samples/ file I
> already wrote.

Right, so I started playing with this, added a global Makefile to tools/
and from there we descend into lib/ and perf/ in that order to prepare
all the modules for the perflib. I've played with the include paths so
that you can have #include <util/util.h> for all that generic library
stuff.

The patch below carves out the debugfs helpers along with some generic
headers, please take a look and let me know if this is an agreeable
direction I'm going. Yeah, it is big, I think vger won't be able to
swallow it but this is only moving files around so...

Thanks.

--
>From 0f391f0acf39d3b2e85145dce389cbf425cb7cdd Mon Sep 17 00:00:00 2001
From: Borislav Petkov <borislav.petkov@amd.com>
Date: Mon, 14 Jun 2010 21:14:15 +0200
Subject: [PATCH] perf: rewire generic library stuff

---
 tools/Makefile                                     |   74 +++++
 tools/lib/Makefile                                 |   41 +++
 tools/lib/util/cache.h                             |   86 ++++++
 tools/lib/util/debugfs.c                           |  252 +++++++++++++++++
 tools/lib/util/debugfs.h                           |   31 +++
 tools/lib/util/strbuf.c                            |  133 +++++++++
 tools/lib/util/strbuf.h                            |   92 +++++++
 tools/lib/util/types.h                             |   17 ++
 tools/lib/util/util.h                              |  282 ++++++++++++++++++++
 tools/perf/Makefile                                |   64 +----
 tools/perf/bench/bench.h                           |    2 +
 tools/perf/bench/mem-memcpy.c                      |    2 +-
 tools/perf/bench/sched-messaging.c                 |    2 +-
 tools/perf/bench/sched-pipe.c                      |    2 +-
 tools/perf/builtin-bench.c                         |    2 +-
 tools/perf/builtin.h                               |    4 +-
 tools/perf/perf.c                                  |   15 +-
 tools/perf/perf.h                                  |    2 +
 tools/perf/util/abspath.c                          |    2 +-
 tools/perf/util/alias.c                            |    3 +-
 tools/perf/util/build-id.c                         |    2 +-
 tools/perf/util/cache.h                            |   86 ------
 tools/perf/util/callchain.c                        |    2 +-
 tools/perf/util/color.c                            |    2 +-
 tools/perf/util/color.h                            |    2 +
 tools/perf/util/config.c                           |    5 +-
 tools/perf/util/cpumap.c                           |    2 +-
 tools/perf/util/ctype.c                            |    2 +-
 tools/perf/util/debug.c                            |    4 +-
 tools/perf/util/debugfs.c                          |  240 -----------------
 tools/perf/util/debugfs.h                          |   25 --
 tools/perf/util/environment.c                      |    2 +-
 tools/perf/util/exec_cmd.c                         |    2 +-
 tools/perf/util/header.c                           |    2 +-
 tools/perf/util/header.h                           |    2 +-
 tools/perf/util/help.c                             |    4 +-
 tools/perf/util/hist.c                             |    2 +-
 tools/perf/util/levenshtein.c                      |    2 +-
 tools/perf/util/map.h                              |    2 +-
 tools/perf/util/newt.c                             |    2 +-
 tools/perf/util/pager.c                            |    2 +-
 tools/perf/util/parse-events.c                     |    8 +-
 tools/perf/util/parse-events.h                     |    4 +-
 tools/perf/util/parse-options.c                    |    5 +-
 tools/perf/util/path.c                             |    2 +-
 tools/perf/util/probe-event.c                      |    6 +-
 tools/perf/util/probe-finder.c                     |    2 +-
 tools/perf/util/probe-finder.h                     |    2 +-
 tools/perf/util/pstack.c                           |    2 +-
 tools/perf/util/quote.c                            |    2 +-
 tools/perf/util/run-command.c                      |    2 +-
 .../perf/util/scripting-engines/trace-event-perl.c |    2 +-
 .../util/scripting-engines/trace-event-python.c    |    2 +-
 tools/perf/util/session.c                          |    2 +-
 tools/perf/util/sigchain.c                         |    2 +-
 tools/perf/util/sort.h                             |    4 +-
 tools/perf/util/strbuf.c                           |  133 ---------
 tools/perf/util/strbuf.h                           |   92 -------
 tools/perf/util/string.c                           |    2 +-
 tools/perf/util/svghelper.h                        |    2 +-
 tools/perf/util/thread.c                           |    2 +-
 tools/perf/util/trace-event-info.c                 |    2 +-
 tools/perf/util/trace-event-parse.c                |    2 +-
 tools/perf/util/trace-event-read.c                 |    2 +-
 tools/perf/util/trace-event-scripting.c            |    2 +-
 tools/perf/util/types.h                            |   17 --
 tools/perf/util/usage.c                            |    2 +-
 tools/perf/util/util.c                             |    2 +-
 tools/perf/util/util.h                             |  282 --------------------
 tools/perf/util/values.c                           |    2 +-
 tools/perf/util/values.h                           |    2 +-
 tools/perf/util/wrapper.c                          |    3 +-
 72 files changed, 1089 insertions(+), 1009 deletions(-)
 create mode 100644 tools/Makefile
 create mode 100644 tools/lib/Makefile
 create mode 100644 tools/lib/util/cache.h
 create mode 100644 tools/lib/util/debugfs.c
 create mode 100644 tools/lib/util/debugfs.h
 create mode 100644 tools/lib/util/strbuf.c
 create mode 100644 tools/lib/util/strbuf.h
 create mode 100644 tools/lib/util/types.h
 create mode 100644 tools/lib/util/util.h
 delete mode 100644 tools/perf/util/cache.h
 delete mode 100644 tools/perf/util/debugfs.c
 delete mode 100644 tools/perf/util/debugfs.h
 delete mode 100644 tools/perf/util/strbuf.c
 delete mode 100644 tools/perf/util/strbuf.h
 delete mode 100644 tools/perf/util/types.h
 delete mode 100644 tools/perf/util/util.h

diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000..34642e6
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,74 @@
+# CFLAGS and LDFLAGS are for the users to override from the command line.
+
+#
+# Include saner warnings here, which can catch bugs:
+#
+
+EXTRA_WARNINGS := -Wformat
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstack-protector
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wvolatile-register-var
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-prototypes
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wnested-externs
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
+EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
+
+export EXTRA_WARNINGS
+
+ifeq ("$(origin DEBUG)", "command line")
+  PERF_DEBUG = $(DEBUG)
+endif
+ifndef PERF_DEBUG
+  CFLAGS_OPTIMIZE = -O6
+endif
+
+ifneq ($(findstring $(MAKEFLAGS),s),s)
+ifndef V
+	QUIET_CC       = @echo '   ' CC $@;
+	QUIET_AR       = @echo '   ' AR $@;
+	QUIET_LINK     = @echo '   ' LINK $@;
+	QUIET_BUILT_IN = @echo '   ' BUILTIN $@;
+	QUIET_GEN      = @echo '   ' GEN $@;
+	QUIET_SUBDIR0  = +@subdir=
+	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
+			 $(MAKE) $(PRINT_DIR) -C $$subdir
+	export V
+	export QUIET_CC
+	export QUIET_GEN
+	export QUIET_BUILT_IN
+endif
+endif
+
+#
+# lib includes for submake
+BASIC_CFLAGS = -I$(CURDIR)/lib
+
+export BASIC_CFLAGS
+
+rasd: lib
+
+perf: lib .FORCE
+	$(MAKE) -C perf/
+
+lib: .FORCE
+	$(MAKE) -C lib/
+
+clean:
+	$(MAKE) -C lib/ clean
+	$(MAKE) -C perf/ clean
+
+.PHONY: clean .FORCE
diff --git a/tools/lib/Makefile b/tools/lib/Makefile
new file mode 100644
index 0000000..faa5a0a
--- /dev/null
+++ b/tools/lib/Makefile
@@ -0,0 +1,41 @@
+ifeq ("$(origin O)", "command line")
+	OUTPUT := $(O)/
+endif
+
+# Guard against environment variables
+LIB_H =
+LIB_OBJS =
+
+LIB_H += util/debugfs.h
+LIB_H += util/util.h
+LIB_H += util/types.h
+LIB_H += util/cache.h
+LIB_H += util/strbuf.h
+
+LIB_OBJS += $(OUTPUT)util/strbuf.o
+LIB_OBJS += $(OUTPUT)util/debugfs.o
+
+RM = rm -f
+
+CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
+EXTLIBS = -lpthread -lrt -lelf -lm
+ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+ALL_LDFLAGS = $(LDFLAGS)
+STRIP ?= strip
+
+genlib.a: $(LIB_OBJS)
+	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
+
+$(LIB_OBJS): $(LIB_H)
+
+$(OUTPUT)%.o: %.c
+	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
+$(OUTPUT)%.s: %.c
+	$(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
+$(OUTPUT)%.o: %.S
+	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
+
+clean:
+	$(RM) $(LIB_OBJS)
+
+.PHONY: clean
diff --git a/tools/lib/util/cache.h b/tools/lib/util/cache.h
new file mode 100644
index 0000000..94939b4
--- /dev/null
+++ b/tools/lib/util/cache.h
@@ -0,0 +1,86 @@
+#ifndef __PERF_CACHE_H
+#define __PERF_CACHE_H
+
+#include <stdbool.h>
+#include "util.h"
+#include "strbuf.h"
+//#include "../../perf/perf.h"
+
+#define CMD_EXEC_PATH "--exec-path"
+#define CMD_PERF_DIR "--perf-dir="
+#define CMD_WORK_TREE "--work-tree="
+#define CMD_DEBUGFS_DIR "--debugfs-dir="
+
+#define PERF_DIR_ENVIRONMENT "PERF_DIR"
+#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
+#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
+#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
+#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
+
+typedef int (*config_fn_t)(const char *, const char *, void *);
+extern int perf_default_config(const char *, const char *, void *);
+extern int perf_config(config_fn_t fn, void *);
+extern int perf_config_int(const char *, const char *);
+extern int perf_config_bool(const char *, const char *);
+extern int config_error_nonbool(const char *);
+
+/* pager.c */
+extern void setup_pager(void);
+extern const char *pager_program;
+extern int pager_in_use(void);
+extern int pager_use_color;
+
+extern int use_browser;
+
+#ifdef NO_NEWT_SUPPORT
+static inline void setup_browser(void)
+{
+	setup_pager();
+}
+static inline void exit_browser(bool wait_for_ok __used) {}
+#else
+void setup_browser(void);
+void exit_browser(bool wait_for_ok);
+#endif
+
+char *alias_lookup(const char *alias);
+int split_cmdline(char *cmdline, const char ***argv);
+
+#define alloc_nr(x) (((x)+16)*3/2)
+
+/*
+ * Realloc the buffer pointed at by variable 'x' so that it can hold
+ * at least 'nr' entries; the number of entries currently allocated
+ * is 'alloc', using the standard growing factor alloc_nr() macro.
+ *
+ * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
+ */
+#define ALLOC_GROW(x, nr, alloc) \
+	do { \
+		if ((nr) > alloc) { \
+			if (alloc_nr(alloc) < (nr)) \
+				alloc = (nr); \
+			else \
+				alloc = alloc_nr(alloc); \
+			x = xrealloc((x), alloc * sizeof(*(x))); \
+		} \
+	} while(0)
+
+
+static inline int is_absolute_path(const char *path)
+{
+	return path[0] == '/';
+}
+
+const char *make_nonrelative_path(const char *path);
+char *strip_path_suffix(const char *path, const char *suffix);
+
+extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+
+extern char *perf_pathdup(const char *fmt, ...)
+	__attribute__((format (printf, 1, 2)));
+
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+
+#endif /* __PERF_CACHE_H */
diff --git a/tools/lib/util/debugfs.c b/tools/lib/util/debugfs.c
new file mode 100644
index 0000000..bb737a5
--- /dev/null
+++ b/tools/lib/util/debugfs.c
@@ -0,0 +1,252 @@
+#include "util.h"
+#include "debugfs.h"
+#include "cache.h"
+
+static int debugfs_premounted;
+static char debugfs_mountpoint[MAX_PATH+1];
+
+char debugfs_path[MAXPATHLEN];
+char debugfs_mntpt[MAXPATHLEN];
+
+static const char *debugfs_known_mountpoints[] = {
+	"/sys/kernel/debug/",
+	"/debug/",
+	0,
+};
+
+/* use this to force a umount */
+void debugfs_force_cleanup(void)
+{
+	debugfs_find_mountpoint();
+	debugfs_premounted = 0;
+	debugfs_umount();
+}
+
+/* construct a full path to a debugfs element */
+int debugfs_make_path(const char *element, char *buffer, int size)
+{
+	int len;
+
+	if (strlen(debugfs_mountpoint) == 0) {
+		buffer[0] = '\0';
+		return -1;
+	}
+
+	len = strlen(debugfs_mountpoint) + strlen(element) + 1;
+	if (len >= size)
+		return len+1;
+
+	snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element);
+	return 0;
+}
+
+static int debugfs_found;
+
+/* find the path to the mounted debugfs */
+const char *debugfs_find_mountpoint(void)
+{
+	const char **ptr;
+	char type[100];
+	FILE *fp;
+
+	if (debugfs_found)
+		return (const char *) debugfs_mountpoint;
+
+	ptr = debugfs_known_mountpoints;
+	while (*ptr) {
+		if (debugfs_valid_mountpoint(*ptr) == 0) {
+			debugfs_found = 1;
+			strcpy(debugfs_mountpoint, *ptr);
+			return debugfs_mountpoint;
+		}
+		ptr++;
+	}
+
+	/* give up and parse /proc/mounts */
+	fp = fopen("/proc/mounts", "r");
+	if (fp == NULL)
+		die("Can't open /proc/mounts for read");
+
+	while (fscanf(fp, "%*s %"
+		      STR(MAX_PATH)
+		      "s %99s %*s %*d %*d\n",
+		      debugfs_mountpoint, type) == 2) {
+		if (strcmp(type, "debugfs") == 0)
+			break;
+	}
+	fclose(fp);
+
+	if (strcmp(type, "debugfs") != 0)
+		return NULL;
+
+	debugfs_found = 1;
+
+	return debugfs_mountpoint;
+}
+
+/* verify that a mountpoint is actually a debugfs instance */
+
+int debugfs_valid_mountpoint(const char *debugfs)
+{
+	struct statfs st_fs;
+
+	if (statfs(debugfs, &st_fs) < 0)
+		return -ENOENT;
+	else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
+		return -ENOENT;
+
+	return 0;
+}
+
+
+int debugfs_valid_entry(const char *path)
+{
+	struct stat st;
+
+	if (stat(path, &st))
+		return -errno;
+
+	return 0;
+}
+
+/* mount the debugfs somewhere if it's not mounted */
+
+char *debugfs_mount(const char *mountpoint)
+{
+	/* see if it's already mounted */
+	if (debugfs_find_mountpoint()) {
+		debugfs_premounted = 1;
+		return debugfs_mountpoint;
+	}
+
+	/* if not mounted and no argument */
+	if (mountpoint == NULL) {
+		/* see if environment variable set */
+		mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
+		/* if no environment variable, use default */
+		if (mountpoint == NULL)
+			mountpoint = "/sys/kernel/debug";
+	}
+
+	if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
+		return NULL;
+
+	/* save the mountpoint */
+	strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
+	debugfs_found = 1;
+
+	return debugfs_mountpoint;
+}
+
+/* umount the debugfs */
+
+int debugfs_umount(void)
+{
+	char umountcmd[128];
+	int ret;
+
+	/* if it was already mounted, leave it */
+	if (debugfs_premounted)
+		return 0;
+
+	/* make sure it's a valid mount point */
+	ret = debugfs_valid_mountpoint(debugfs_mountpoint);
+	if (ret)
+		return ret;
+
+	snprintf(umountcmd, sizeof(umountcmd),
+		 "/bin/umount %s", debugfs_mountpoint);
+	return system(umountcmd);
+}
+
+int debugfs_write(const char *entry, const char *value)
+{
+	char path[MAX_PATH+1];
+	int ret, count;
+	int fd;
+
+	/* construct the path */
+	snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
+
+	/* verify that it exists */
+	ret = debugfs_valid_entry(path);
+	if (ret)
+		return ret;
+
+	/* get how many chars we're going to write */
+	count = strlen(value);
+
+	/* open the debugfs entry */
+	fd = open(path, O_RDWR);
+	if (fd < 0)
+		return -errno;
+
+	while (count > 0) {
+		/* write it */
+		ret = write(fd, value, count);
+		if (ret <= 0) {
+			if (ret == EAGAIN)
+				continue;
+			close(fd);
+			return -errno;
+		}
+		count -= ret;
+	}
+
+	/* close it */
+	close(fd);
+
+	/* return success */
+	return 0;
+}
+
+/*
+ * read a debugfs entry
+ * returns the number of chars read or a negative errno
+ */
+int debugfs_read(const char *entry, char *buffer, size_t size)
+{
+	char path[MAX_PATH+1];
+	int ret;
+	int fd;
+
+	/* construct the path */
+	snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
+
+	/* verify that it exists */
+	ret = debugfs_valid_entry(path);
+	if (ret)
+		return ret;
+
+	/* open the debugfs entry */
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		return -errno;
+
+	do {
+		/* read it */
+		ret = read(fd, buffer, size);
+		if (ret == 0) {
+			close(fd);
+			return EOF;
+		}
+	} while (ret < 0 && errno == EAGAIN);
+
+	/* close it */
+	close(fd);
+
+	/* make *sure* there's a null character at the end */
+	buffer[ret] = '\0';
+
+	/* return the number of chars read */
+	return ret;
+}
+
+void set_debugfs_path(void)
+{
+	char *path;
+
+	path = getenv(PERF_DEBUGFS_ENVIRONMENT);
+	snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
+		 "tracing/events");
+}
diff --git a/tools/lib/util/debugfs.h b/tools/lib/util/debugfs.h
new file mode 100644
index 0000000..dce74b0
--- /dev/null
+++ b/tools/lib/util/debugfs.h
@@ -0,0 +1,31 @@
+#ifndef __DEBUGFS_H__
+#define __DEBUGFS_H__
+
+#include <sys/mount.h>
+#include <sys/param.h>
+
+#ifndef MAX_PATH
+# define MAX_PATH 256
+#endif
+
+#ifndef STR
+# define _STR(x) #x
+# define STR(x) _STR(x)
+#endif
+
+extern char debugfs_path[MAXPATHLEN];
+extern char debugfs_mntpt[MAXPATHLEN];
+
+
+extern const char *debugfs_find_mountpoint(void);
+extern int debugfs_valid_mountpoint(const char *debugfs);
+extern int debugfs_valid_entry(const char *path);
+extern char *debugfs_mount(const char *mountpoint);
+extern int debugfs_umount(void);
+extern int debugfs_write(const char *entry, const char *value);
+extern int debugfs_read(const char *entry, char *buffer, size_t size);
+extern void debugfs_force_cleanup(void);
+extern int debugfs_make_path(const char *element, char *buffer, int size);
+extern void set_debugfs_path(void);
+
+#endif /* __DEBUGFS_H__ */
diff --git a/tools/lib/util/strbuf.c b/tools/lib/util/strbuf.c
new file mode 100644
index 0000000..92e0685
--- /dev/null
+++ b/tools/lib/util/strbuf.c
@@ -0,0 +1,133 @@
+#include "cache.h"
+
+int prefixcmp(const char *str, const char *prefix)
+{
+	for (; ; str++, prefix++)
+		if (!*prefix)
+			return 0;
+		else if (*str != *prefix)
+			return (unsigned char)*prefix - (unsigned char)*str;
+}
+
+/*
+ * Used as the default ->buf value, so that people can always assume
+ * buf is non NULL and ->buf is NUL terminated even for a freshly
+ * initialized strbuf.
+ */
+char strbuf_slopbuf[1];
+
+void strbuf_init(struct strbuf *sb, ssize_t hint)
+{
+	sb->alloc = sb->len = 0;
+	sb->buf = strbuf_slopbuf;
+	if (hint)
+		strbuf_grow(sb, hint);
+}
+
+void strbuf_release(struct strbuf *sb)
+{
+	if (sb->alloc) {
+		free(sb->buf);
+		strbuf_init(sb, 0);
+	}
+}
+
+char *strbuf_detach(struct strbuf *sb, size_t *sz)
+{
+	char *res = sb->alloc ? sb->buf : NULL;
+	if (sz)
+		*sz = sb->len;
+	strbuf_init(sb, 0);
+	return res;
+}
+
+void strbuf_grow(struct strbuf *sb, size_t extra)
+{
+	if (sb->len + extra + 1 <= sb->len)
+		die("you want to use way too much memory");
+	if (!sb->alloc)
+		sb->buf = NULL;
+	ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
+}
+
+static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
+				   const void *data, size_t dlen)
+{
+	if (pos + len < pos)
+		die("you want to use way too much memory");
+	if (pos > sb->len)
+		die("`pos' is too far after the end of the buffer");
+	if (pos + len > sb->len)
+		die("`pos + len' is too far after the end of the buffer");
+
+	if (dlen >= len)
+		strbuf_grow(sb, dlen - len);
+	memmove(sb->buf + pos + dlen,
+			sb->buf + pos + len,
+			sb->len - pos - len);
+	memcpy(sb->buf + pos, data, dlen);
+	strbuf_setlen(sb, sb->len + dlen - len);
+}
+
+void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
+{
+	strbuf_splice(sb, pos, len, NULL, 0);
+}
+
+void strbuf_add(struct strbuf *sb, const void *data, size_t len)
+{
+	strbuf_grow(sb, len);
+	memcpy(sb->buf + sb->len, data, len);
+	strbuf_setlen(sb, sb->len + len);
+}
+
+void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
+{
+	int len;
+	va_list ap;
+
+	if (!strbuf_avail(sb))
+		strbuf_grow(sb, 64);
+	va_start(ap, fmt);
+	len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
+	va_end(ap);
+	if (len < 0)
+		die("your vsnprintf is broken");
+	if (len > strbuf_avail(sb)) {
+		strbuf_grow(sb, len);
+		va_start(ap, fmt);
+		len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
+		va_end(ap);
+		if (len > strbuf_avail(sb)) {
+			die("this should not happen, your snprintf is broken");
+		}
+	}
+	strbuf_setlen(sb, sb->len + len);
+}
+
+ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
+{
+	size_t oldlen = sb->len;
+	size_t oldalloc = sb->alloc;
+
+	strbuf_grow(sb, hint ? hint : 8192);
+	for (;;) {
+		ssize_t cnt;
+
+		cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
+		if (cnt < 0) {
+			if (oldalloc == 0)
+				strbuf_release(sb);
+			else
+				strbuf_setlen(sb, oldlen);
+			return -1;
+		}
+		if (!cnt)
+			break;
+		sb->len += cnt;
+		strbuf_grow(sb, 8192);
+	}
+
+	sb->buf[sb->len] = '\0';
+	return sb->len - oldlen;
+}
diff --git a/tools/lib/util/strbuf.h b/tools/lib/util/strbuf.h
new file mode 100644
index 0000000..436ac31
--- /dev/null
+++ b/tools/lib/util/strbuf.h
@@ -0,0 +1,92 @@
+#ifndef __PERF_STRBUF_H
+#define __PERF_STRBUF_H
+
+/*
+ * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
+ * long, overflow safe strings.
+ *
+ * Strbufs has some invariants that are very important to keep in mind:
+ *
+ * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to
+ *    build complex strings/buffers whose final size isn't easily known.
+ *
+ *    It is NOT legal to copy the ->buf pointer away.
+ *    `strbuf_detach' is the operation that detachs a buffer from its shell
+ *    while keeping the shell valid wrt its invariants.
+ *
+ * 2. the ->buf member is a byte array that has at least ->len + 1 bytes
+ *    allocated. The extra byte is used to store a '\0', allowing the ->buf
+ *    member to be a valid C-string. Every strbuf function ensure this
+ *    invariant is preserved.
+ *
+ *    Note that it is OK to "play" with the buffer directly if you work it
+ *    that way:
+ *
+ *    strbuf_grow(sb, SOME_SIZE);
+ *       ... Here, the memory array starting at sb->buf, and of length
+ *       ... strbuf_avail(sb) is all yours, and you are sure that
+ *       ... strbuf_avail(sb) is at least SOME_SIZE.
+ *    strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE);
+ *
+ *    Of course, SOME_OTHER_SIZE must be smaller or equal to strbuf_avail(sb).
+ *
+ *    Doing so is safe, though if it has to be done in many places, adding the
+ *    missing API to the strbuf module is the way to go.
+ *
+ *    XXX: do _not_ assume that the area that is yours is of size ->alloc - 1
+ *         even if it's true in the current implementation. Alloc is somehow a
+ *         "private" member that should not be messed with.
+ */
+
+#include <assert.h>
+
+extern char strbuf_slopbuf[];
+struct strbuf {
+	size_t alloc;
+	size_t len;
+	char *buf;
+};
+
+#define STRBUF_INIT  { 0, 0, strbuf_slopbuf }
+
+/*----- strbuf life cycle -----*/
+extern void strbuf_init(struct strbuf *buf, ssize_t hint);
+extern void strbuf_release(struct strbuf *);
+extern char *strbuf_detach(struct strbuf *, size_t *);
+
+/*----- strbuf size related -----*/
+static inline ssize_t strbuf_avail(const struct strbuf *sb) {
+	return sb->alloc ? sb->alloc - sb->len - 1 : 0;
+}
+
+extern void strbuf_grow(struct strbuf *, size_t);
+
+static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
+	if (!sb->alloc)
+		strbuf_grow(sb, 0);
+	assert(len < sb->alloc);
+	sb->len = len;
+	sb->buf[len] = '\0';
+}
+
+/*----- add data in your buffer -----*/
+static inline void strbuf_addch(struct strbuf *sb, int c) {
+	strbuf_grow(sb, 1);
+	sb->buf[sb->len++] = c;
+	sb->buf[sb->len] = '\0';
+}
+
+extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);
+
+extern void strbuf_add(struct strbuf *, const void *, size_t);
+static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
+	strbuf_add(sb, s, strlen(s));
+}
+
+__attribute__((format(printf,2,3)))
+extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
+
+/* XXX: if read fails, any partial read is undone */
+extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
+
+#endif /* __PERF_STRBUF_H */
diff --git a/tools/lib/util/types.h b/tools/lib/util/types.h
new file mode 100644
index 0000000..7d6b833
--- /dev/null
+++ b/tools/lib/util/types.h
@@ -0,0 +1,17 @@
+#ifndef __PERF_TYPES_H
+#define __PERF_TYPES_H
+
+/*
+ * We define u64 as unsigned long long for every architecture
+ * so that we can print it with %Lx without getting warnings.
+ */
+typedef unsigned long long u64;
+typedef signed long long   s64;
+typedef unsigned int	   u32;
+typedef signed int	   s32;
+typedef unsigned short	   u16;
+typedef signed short	   s16;
+typedef unsigned char	   u8;
+typedef signed char	   s8;
+
+#endif /* __PERF_TYPES_H */
diff --git a/tools/lib/util/util.h b/tools/lib/util/util.h
new file mode 100644
index 0000000..4e8b6b0
--- /dev/null
+++ b/tools/lib/util/util.h
@@ -0,0 +1,282 @@
+#ifndef GIT_COMPAT_UTIL_H
+#define GIT_COMPAT_UTIL_H
+
+#define _FILE_OFFSET_BITS 64
+
+#ifndef FLEX_ARRAY
+/*
+ * See if our compiler is known to support flexible array members.
+ */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEX_ARRAY /* empty */
+#elif defined(__GNUC__)
+# if (__GNUC__ >= 3)
+#  define FLEX_ARRAY /* empty */
+# else
+#  define FLEX_ARRAY 0 /* older GNU extension */
+# endif
+#endif
+
+/*
+ * Otherwise, default to safer but a bit wasteful traditional style
+ */
+#ifndef FLEX_ARRAY
+# define FLEX_ARRAY 1
+#endif
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+#ifdef __GNUC__
+#define TYPEOF(x) (__typeof__(x))
+#else
+#define TYPEOF(x)
+#endif
+
+#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
+#define HAS_MULTI_BITS(i)  ((i) & ((i) - 1))  /* checks if an integer has more than 1 bit set */
+
+/* Approximation of the length of the decimal representation of this type. */
+#define decimal_length(x)	((int)(sizeof(x) * 2.56 + 0.5) + 1)
+
+#define _ALL_SOURCE 1
+#define _GNU_SOURCE 1
+#define _BSD_SOURCE 1
+#define HAS_BOOL
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
+#include <signal.h>
+#include <fnmatch.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#include <sys/wait.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#ifndef NO_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <inttypes.h>
+#include "../../../include/linux/magic.h"
+#include "types.h"
+#include <sys/ttydefaults.h>
+
+#ifndef NO_ICONV
+#include <iconv.h>
+#endif
+
+extern const char *graph_line;
+extern const char *graph_dotted_line;
+
+/* On most systems <limits.h> would have given us this, but
+ * not on some systems (e.g. GNU/Hurd).
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
+#ifndef PRIuMAX
+#define PRIuMAX "llu"
+#endif
+
+#ifndef PRIu32
+#define PRIu32 "u"
+#endif
+
+#ifndef PRIx32
+#define PRIx32 "x"
+#endif
+
+#ifndef PATH_SEP
+#define PATH_SEP ':'
+#endif
+
+#ifndef STRIP_EXTENSION
+#define STRIP_EXTENSION ""
+#endif
+
+#ifndef has_dos_drive_prefix
+#define has_dos_drive_prefix(path) 0
+#endif
+
+#ifndef is_dir_sep
+#define is_dir_sep(c) ((c) == '/')
+#endif
+
+#ifdef __GNUC__
+#define NORETURN __attribute__((__noreturn__))
+#else
+#define NORETURN
+#ifndef __attribute__
+#define __attribute__(x)
+#endif
+#endif
+
+/* General helper functions */
+extern void usage(const char *err) NORETURN;
+extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
+extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
+extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
+
+#include "../../../include/linux/stringify.h"
+
+#define DIE_IF(cnd)	\
+	do { if (cnd)	\
+		die(" at (" __FILE__ ":" __stringify(__LINE__) "): "	\
+		    __stringify(cnd) "\n");				\
+	} while (0)
+
+
+extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
+
+extern int prefixcmp(const char *str, const char *prefix);
+
+static inline const char *skip_prefix(const char *str, const char *prefix)
+{
+	size_t len = strlen(prefix);
+	return strncmp(str, prefix, len) ? NULL : str + len;
+}
+
+#ifdef __GLIBC_PREREQ
+#if __GLIBC_PREREQ(2, 1)
+#define HAVE_STRCHRNUL
+#endif
+#endif
+
+#ifndef HAVE_STRCHRNUL
+#define strchrnul gitstrchrnul
+static inline char *gitstrchrnul(const char *s, int c)
+{
+	while (*s && *s != c)
+		s++;
+	return (char *)s;
+}
+#endif
+
+/*
+ * Wrappers:
+ */
+extern char *xstrdup(const char *str);
+extern void *xrealloc(void *ptr, size_t size) __attribute__((weak));
+
+
+static inline void *zalloc(size_t size)
+{
+	return calloc(1, size);
+}
+
+static inline int has_extension(const char *filename, const char *ext)
+{
+	size_t len = strlen(filename);
+	size_t extlen = strlen(ext);
+
+	return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
+}
+
+/* Sane ctype - no locale, and works with signed chars */
+#undef isascii
+#undef isspace
+#undef isdigit
+#undef isxdigit
+#undef isalpha
+#undef isprint
+#undef isalnum
+#undef tolower
+#undef toupper
+
+extern unsigned char sane_ctype[256];
+#define GIT_SPACE		0x01
+#define GIT_DIGIT		0x02
+#define GIT_ALPHA		0x04
+#define GIT_GLOB_SPECIAL	0x08
+#define GIT_REGEX_SPECIAL	0x10
+#define GIT_PRINT_EXTRA		0x20
+#define GIT_PRINT		0x3E
+#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
+#define isascii(x) (((x) & ~0x7f) == 0)
+#define isspace(x) sane_istest(x,GIT_SPACE)
+#define isdigit(x) sane_istest(x,GIT_DIGIT)
+#define isxdigit(x)	\
+	(sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
+#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 tolower(x) sane_case((unsigned char)(x), 0x20)
+#define toupper(x) sane_case((unsigned char)(x), 0)
+
+static inline int sane_case(int x, int high)
+{
+	if (sane_istest(x, GIT_ALPHA))
+		x = (x & ~0x20) | high;
+	return x;
+}
+
+#ifndef DIR_HAS_BSD_GROUP_SEMANTICS
+# define FORCE_DIR_SET_GID S_ISGID
+#else
+# define FORCE_DIR_SET_GID 0
+#endif
+
+#ifdef NO_NSEC
+#undef USE_NSEC
+#define ST_CTIME_NSEC(st) 0
+#define ST_MTIME_NSEC(st) 0
+#else
+#ifdef USE_ST_TIMESPEC
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
+#else
+#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
+#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
+#endif
+#endif
+
+int mkdir_p(char *path, mode_t mode);
+int copyfile(const char *from, const char *to);
+
+s64 perf_atoll(const char *str);
+char **argv_split(const char *str, int *argcp);
+void argv_free(char **argv);
+bool strglobmatch(const char *str, const char *pat);
+bool strlazymatch(const char *str, const char *pat);
+unsigned long convert_unit(unsigned long value, char *unit);
+
+#ifndef ESC
+#define ESC 27
+#endif
+
+static inline bool is_exit_key(int key)
+{
+	char up;
+	if (key == CTRL('c') || key == ESC)
+		return true;
+	up = toupper(key);
+	return up == 'Q';
+}
+
+#define _STR(x) #x
+#define STR(x) _STR(x)
+
+#endif
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 3d8f31e..fac008c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -189,42 +189,6 @@ endif
 
 $(shell sh -c 'mkdir -p $(OUTPUT)arch/$(ARCH)/util/' 2> /dev/null)
 
-# CFLAGS and LDFLAGS are for the users to override from the command line.
-
-#
-# Include saner warnings here, which can catch bugs:
-#
-
-EXTRA_WARNINGS := -Wformat
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-security
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wformat-y2k
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wshadow
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Winit-self
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wpacked
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wredundant-decls
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstack-protector
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-aliasing=3
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-default
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wswitch-enum
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wno-system-headers
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wundef
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wvolatile-register-var
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wwrite-strings
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wbad-function-cast
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-declarations
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wmissing-prototypes
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wnested-externs
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wold-style-definition
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wstrict-prototypes
-EXTRA_WARNINGS := $(EXTRA_WARNINGS) -Wdeclaration-after-statement
-
-ifeq ("$(origin DEBUG)", "command line")
-  PERF_DEBUG = $(DEBUG)
-endif
-ifndef PERF_DEBUG
-  CFLAGS_OPTIMIZE = -O6
-endif
-
 CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
 EXTLIBS = -lpthread -lrt -lelf -lm
 ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
@@ -301,7 +265,7 @@ endif
 # 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 = -Iutil/include -Iarch/$(ARCH)/include
+BASIC_CFLAGS += -Iutil/include -Iarch/$(ARCH)/include
 BASIC_LDFLAGS =
 
 # Guard against environment variables
@@ -385,24 +349,19 @@ LIB_H += util/include/asm/system.h
 LIB_H += util/include/asm/uaccess.h
 LIB_H += util/include/dwarf-regs.h
 LIB_H += perf.h
-LIB_H += util/cache.h
 LIB_H += util/callchain.h
 LIB_H += util/build-id.h
 LIB_H += util/debug.h
-LIB_H += util/debugfs.h
 LIB_H += util/event.h
 LIB_H += util/exec_cmd.h
-LIB_H += util/types.h
 LIB_H += util/levenshtein.h
 LIB_H += util/map.h
 LIB_H += util/parse-options.h
 LIB_H += util/parse-events.h
 LIB_H += util/quote.h
-LIB_H += util/util.h
 LIB_H += util/header.h
 LIB_H += util/help.h
 LIB_H += util/session.h
-LIB_H += util/strbuf.h
 LIB_H += util/strlist.h
 LIB_H += util/svghelper.h
 LIB_H += util/run-command.h
@@ -419,12 +378,14 @@ LIB_H += util/probe-event.h
 LIB_H += util/pstack.h
 LIB_H += util/cpumap.h
 
+# add generic library modules
+LIB_OBJS := $(wildcard ../lib/util/*.o)
+
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
 LIB_OBJS += $(OUTPUT)util/build-id.o
 LIB_OBJS += $(OUTPUT)util/config.o
 LIB_OBJS += $(OUTPUT)util/ctype.o
-LIB_OBJS += $(OUTPUT)util/debugfs.o
 LIB_OBJS += $(OUTPUT)util/environment.o
 LIB_OBJS += $(OUTPUT)util/event.o
 LIB_OBJS += $(OUTPUT)util/exec_cmd.o
@@ -438,7 +399,6 @@ LIB_OBJS += $(OUTPUT)util/bitmap.o
 LIB_OBJS += $(OUTPUT)util/hweight.o
 LIB_OBJS += $(OUTPUT)util/run-command.o
 LIB_OBJS += $(OUTPUT)util/quote.o
-LIB_OBJS += $(OUTPUT)util/strbuf.o
 LIB_OBJS += $(OUTPUT)util/string.o
 LIB_OBJS += $(OUTPUT)util/strlist.o
 LIB_OBJS += $(OUTPUT)util/usage.o
@@ -811,22 +771,6 @@ else # "make -w"
 NO_SUBDIR = :
 endif
 
-ifneq ($(findstring $(MAKEFLAGS),s),s)
-ifndef V
-	QUIET_CC       = @echo '   ' CC $@;
-	QUIET_AR       = @echo '   ' AR $@;
-	QUIET_LINK     = @echo '   ' LINK $@;
-	QUIET_BUILT_IN = @echo '   ' BUILTIN $@;
-	QUIET_GEN      = @echo '   ' GEN $@;
-	QUIET_SUBDIR0  = +@subdir=
-	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
-			 $(MAKE) $(PRINT_DIR) -C $$subdir
-	export V
-	export QUIET_GEN
-	export QUIET_BUILT_IN
-endif
-endif
-
 ifdef ASCIIDOC8
 	export ASCIIDOC8
 endif
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index f7781c6..0c7ee07 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -1,6 +1,8 @@
 #ifndef BENCH_H
 #define BENCH_H
 
+#include <linux/compiler.h>
+
 extern int bench_sched_messaging(int argc, const char **argv, const char *prefix);
 extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
 extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used);
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 38dae74..e0fec0d 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -8,7 +8,7 @@
 #include <ctype.h>
 
 #include "../perf.h"
-#include "../util/util.h"
+#include <util/util.h>
 #include "../util/parse-options.h"
 #include "../util/header.h"
 #include "bench.h"
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index d1d1b30..fac36b5 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -10,7 +10,7 @@
  */
 
 #include "../perf.h"
-#include "../util/util.h"
+#include <util/util.h>
 #include "../util/parse-options.h"
 #include "../builtin.h"
 #include "bench.h"
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index d9ab3ce..e7bb3d9 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -11,7 +11,7 @@
  */
 
 #include "../perf.h"
-#include "../util/util.h"
+#include <util/util.h>
 #include "../util/parse-options.h"
 #include "../builtin.h"
 #include "bench.h"
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index fcb9626..a083106 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -17,7 +17,7 @@
  */
 
 #include "perf.h"
-#include "util/util.h"
+#include <util/util.h>
 #include "util/parse-options.h"
 #include "builtin.h"
 #include "bench/bench.h"
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index 921245b..0b65de4 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -1,8 +1,8 @@
 #ifndef BUILTIN_H
 #define BUILTIN_H
 
-#include "util/util.h"
-#include "util/strbuf.h"
+#include <util/util.h>
+#include <util/strbuf.h>
 
 extern const char perf_version_string[];
 extern const char perf_usage_string[];
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 6e48711..ee5c28d 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -9,11 +9,11 @@
 #include "builtin.h"
 
 #include "util/exec_cmd.h"
-#include "util/cache.h"
+#include <util/cache.h>
 #include "util/quote.h"
 #include "util/run-command.h"
 #include "util/parse-events.h"
-#include "util/debugfs.h"
+#include <util/debugfs.h>
 
 const char perf_usage_string[] =
 	"perf [--version] [--help] COMMAND [ARGS]";
@@ -29,8 +29,6 @@ struct pager_config {
 	int val;
 };
 
-static char debugfs_mntpt[MAXPATHLEN];
-
 static int pager_command_config(const char *var, const char *value, void *data)
 {
 	struct pager_config *c = data;
@@ -81,15 +79,6 @@ static void commit_pager_choice(void)
 	}
 }
 
-static void set_debugfs_path(void)
-{
-	char *path;
-
-	path = getenv(PERF_DEBUGFS_ENVIRONMENT);
-	snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
-		 "tracing/events");
-}
-
 static int handle_options(const char ***argv, int *argc, int *envchanged)
 {
 	int handled = 0;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index ef7aa0a..e235f6a 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -1,6 +1,8 @@
 #ifndef _PERF_PERF_H
 #define _PERF_PERF_H
 
+#include <linux/compiler.h>
+
 struct winsize;
 
 void get_term_dimensions(struct winsize *ws);
diff --git a/tools/perf/util/abspath.c b/tools/perf/util/abspath.c
index 0e76aff..659125d 100644
--- a/tools/perf/util/abspath.c
+++ b/tools/perf/util/abspath.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include <util/cache.h>
 
 static const char *get_pwd_cwd(void)
 {
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
index b8144e8..1d13065 100644
--- a/tools/perf/util/alias.c
+++ b/tools/perf/util/alias.c
@@ -1,4 +1,5 @@
-#include "cache.h"
+#include <linux/compiler.h>
+#include <util/cache.h>
 
 static const char *alias_key;
 static char *alias_val;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 70c5cf8..d25de52 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -6,7 +6,7 @@
  * Copyright (C) 2009, 2010 Red Hat Inc.
  * Copyright (C) 2009, 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
  */
-#include "util.h"
+#include <util/util.h>
 #include <stdio.h>
 #include "build-id.h"
 #include "event.h"
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
deleted file mode 100644
index 65fe664..0000000
--- a/tools/perf/util/cache.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef __PERF_CACHE_H
-#define __PERF_CACHE_H
-
-#include <stdbool.h>
-#include "util.h"
-#include "strbuf.h"
-#include "../perf.h"
-
-#define CMD_EXEC_PATH "--exec-path"
-#define CMD_PERF_DIR "--perf-dir="
-#define CMD_WORK_TREE "--work-tree="
-#define CMD_DEBUGFS_DIR "--debugfs-dir="
-
-#define PERF_DIR_ENVIRONMENT "PERF_DIR"
-#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
-#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
-#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
-#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
-
-typedef int (*config_fn_t)(const char *, const char *, void *);
-extern int perf_default_config(const char *, const char *, void *);
-extern int perf_config(config_fn_t fn, void *);
-extern int perf_config_int(const char *, const char *);
-extern int perf_config_bool(const char *, const char *);
-extern int config_error_nonbool(const char *);
-
-/* pager.c */
-extern void setup_pager(void);
-extern const char *pager_program;
-extern int pager_in_use(void);
-extern int pager_use_color;
-
-extern int use_browser;
-
-#ifdef NO_NEWT_SUPPORT
-static inline void setup_browser(void)
-{
-	setup_pager();
-}
-static inline void exit_browser(bool wait_for_ok __used) {}
-#else
-void setup_browser(void);
-void exit_browser(bool wait_for_ok);
-#endif
-
-char *alias_lookup(const char *alias);
-int split_cmdline(char *cmdline, const char ***argv);
-
-#define alloc_nr(x) (((x)+16)*3/2)
-
-/*
- * Realloc the buffer pointed at by variable 'x' so that it can hold
- * at least 'nr' entries; the number of entries currently allocated
- * is 'alloc', using the standard growing factor alloc_nr() macro.
- *
- * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
- */
-#define ALLOC_GROW(x, nr, alloc) \
-	do { \
-		if ((nr) > alloc) { \
-			if (alloc_nr(alloc) < (nr)) \
-				alloc = (nr); \
-			else \
-				alloc = alloc_nr(alloc); \
-			x = xrealloc((x), alloc * sizeof(*(x))); \
-		} \
-	} while(0)
-
-
-static inline int is_absolute_path(const char *path)
-{
-	return path[0] == '/';
-}
-
-const char *make_nonrelative_path(const char *path);
-char *strip_path_suffix(const char *path, const char *suffix);
-
-extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
-extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
-
-extern char *perf_pathdup(const char *fmt, ...)
-	__attribute__((format (printf, 1, 2)));
-
-extern size_t strlcpy(char *dest, const char *src, size_t size);
-
-#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 62b69ad..73f8cf0 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -15,7 +15,7 @@
 #include <errno.h>
 #include <math.h>
 
-#include "util.h"
+#include <util/util.h>
 #include "callchain.h"
 
 bool ip_callchain__valid(struct ip_callchain *chain, event_t *event)
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index e191eb9..0e8edc4 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include <util/cache.h>
 #include "color.h"
 
 int perf_use_color_default = -1;
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index dea082b..9ffab44 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -1,6 +1,8 @@
 #ifndef __PERF_COLOR_H
 #define __PERF_COLOR_H
 
+#include <stddef.h>
+
 /* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
 #define COLOR_MAXLEN 24
 
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index dabe892..d199791 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -5,8 +5,9 @@
  * Copyright (C) Johannes Schindelin, 2005
  *
  */
-#include "util.h"
-#include "cache.h"
+#include <util/util.h>
+#include <util/cache.h>
+#include <linux/compiler.h>
 #include "exec_cmd.h"
 
 #define MAXNAME (256)
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 4e01490..47335ce 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -1,4 +1,4 @@
-#include "util.h"
+#include <util/util.h>
 #include "../perf.h"
 #include "cpumap.h"
 #include <assert.h>
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index 3507362..ec47e62 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -3,7 +3,7 @@
  *
  * No surprises, and works with signed and unsigned chars.
  */
-#include "cache.h"
+#include <util/cache.h>
 
 enum {
 	S = GIT_SPACE,
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index dd824cf..b53e41c 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -6,11 +6,11 @@
 #include <stdarg.h>
 #include <stdio.h>
 
-#include "cache.h"
+#include <util/cache.h>
 #include "color.h"
 #include "event.h"
 #include "debug.h"
-#include "util.h"
+#include <util/util.h>
 
 int verbose = 0;
 bool dump_trace = false;
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
deleted file mode 100644
index a88fefc..0000000
--- a/tools/perf/util/debugfs.c
+++ /dev/null
@@ -1,240 +0,0 @@
-#include "util.h"
-#include "debugfs.h"
-#include "cache.h"
-
-static int debugfs_premounted;
-static char debugfs_mountpoint[MAX_PATH+1];
-
-static const char *debugfs_known_mountpoints[] = {
-	"/sys/kernel/debug/",
-	"/debug/",
-	0,
-};
-
-/* use this to force a umount */
-void debugfs_force_cleanup(void)
-{
-	debugfs_find_mountpoint();
-	debugfs_premounted = 0;
-	debugfs_umount();
-}
-
-/* construct a full path to a debugfs element */
-int debugfs_make_path(const char *element, char *buffer, int size)
-{
-	int len;
-
-	if (strlen(debugfs_mountpoint) == 0) {
-		buffer[0] = '\0';
-		return -1;
-	}
-
-	len = strlen(debugfs_mountpoint) + strlen(element) + 1;
-	if (len >= size)
-		return len+1;
-
-	snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element);
-	return 0;
-}
-
-static int debugfs_found;
-
-/* find the path to the mounted debugfs */
-const char *debugfs_find_mountpoint(void)
-{
-	const char **ptr;
-	char type[100];
-	FILE *fp;
-
-	if (debugfs_found)
-		return (const char *) debugfs_mountpoint;
-
-	ptr = debugfs_known_mountpoints;
-	while (*ptr) {
-		if (debugfs_valid_mountpoint(*ptr) == 0) {
-			debugfs_found = 1;
-			strcpy(debugfs_mountpoint, *ptr);
-			return debugfs_mountpoint;
-		}
-		ptr++;
-	}
-
-	/* give up and parse /proc/mounts */
-	fp = fopen("/proc/mounts", "r");
-	if (fp == NULL)
-		die("Can't open /proc/mounts for read");
-
-	while (fscanf(fp, "%*s %"
-		      STR(MAX_PATH)
-		      "s %99s %*s %*d %*d\n",
-		      debugfs_mountpoint, type) == 2) {
-		if (strcmp(type, "debugfs") == 0)
-			break;
-	}
-	fclose(fp);
-
-	if (strcmp(type, "debugfs") != 0)
-		return NULL;
-
-	debugfs_found = 1;
-
-	return debugfs_mountpoint;
-}
-
-/* verify that a mountpoint is actually a debugfs instance */
-
-int debugfs_valid_mountpoint(const char *debugfs)
-{
-	struct statfs st_fs;
-
-	if (statfs(debugfs, &st_fs) < 0)
-		return -ENOENT;
-	else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
-		return -ENOENT;
-
-	return 0;
-}
-
-
-int debugfs_valid_entry(const char *path)
-{
-	struct stat st;
-
-	if (stat(path, &st))
-		return -errno;
-
-	return 0;
-}
-
-/* mount the debugfs somewhere if it's not mounted */
-
-char *debugfs_mount(const char *mountpoint)
-{
-	/* see if it's already mounted */
-	if (debugfs_find_mountpoint()) {
-		debugfs_premounted = 1;
-		return debugfs_mountpoint;
-	}
-
-	/* if not mounted and no argument */
-	if (mountpoint == NULL) {
-		/* see if environment variable set */
-		mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
-		/* if no environment variable, use default */
-		if (mountpoint == NULL)
-			mountpoint = "/sys/kernel/debug";
-	}
-
-	if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
-		return NULL;
-
-	/* save the mountpoint */
-	strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
-	debugfs_found = 1;
-
-	return debugfs_mountpoint;
-}
-
-/* umount the debugfs */
-
-int debugfs_umount(void)
-{
-	char umountcmd[128];
-	int ret;
-
-	/* if it was already mounted, leave it */
-	if (debugfs_premounted)
-		return 0;
-
-	/* make sure it's a valid mount point */
-	ret = debugfs_valid_mountpoint(debugfs_mountpoint);
-	if (ret)
-		return ret;
-
-	snprintf(umountcmd, sizeof(umountcmd),
-		 "/bin/umount %s", debugfs_mountpoint);
-	return system(umountcmd);
-}
-
-int debugfs_write(const char *entry, const char *value)
-{
-	char path[MAX_PATH+1];
-	int ret, count;
-	int fd;
-
-	/* construct the path */
-	snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
-
-	/* verify that it exists */
-	ret = debugfs_valid_entry(path);
-	if (ret)
-		return ret;
-
-	/* get how many chars we're going to write */
-	count = strlen(value);
-
-	/* open the debugfs entry */
-	fd = open(path, O_RDWR);
-	if (fd < 0)
-		return -errno;
-
-	while (count > 0) {
-		/* write it */
-		ret = write(fd, value, count);
-		if (ret <= 0) {
-			if (ret == EAGAIN)
-				continue;
-			close(fd);
-			return -errno;
-		}
-		count -= ret;
-	}
-
-	/* close it */
-	close(fd);
-
-	/* return success */
-	return 0;
-}
-
-/*
- * read a debugfs entry
- * returns the number of chars read or a negative errno
- */
-int debugfs_read(const char *entry, char *buffer, size_t size)
-{
-	char path[MAX_PATH+1];
-	int ret;
-	int fd;
-
-	/* construct the path */
-	snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
-
-	/* verify that it exists */
-	ret = debugfs_valid_entry(path);
-	if (ret)
-		return ret;
-
-	/* open the debugfs entry */
-	fd = open(path, O_RDONLY);
-	if (fd < 0)
-		return -errno;
-
-	do {
-		/* read it */
-		ret = read(fd, buffer, size);
-		if (ret == 0) {
-			close(fd);
-			return EOF;
-		}
-	} while (ret < 0 && errno == EAGAIN);
-
-	/* close it */
-	close(fd);
-
-	/* make *sure* there's a null character at the end */
-	buffer[ret] = '\0';
-
-	/* return the number of chars read */
-	return ret;
-}
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
deleted file mode 100644
index 83a0287..0000000
--- a/tools/perf/util/debugfs.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __DEBUGFS_H__
-#define __DEBUGFS_H__
-
-#include <sys/mount.h>
-
-#ifndef MAX_PATH
-# define MAX_PATH 256
-#endif
-
-#ifndef STR
-# define _STR(x) #x
-# define STR(x) _STR(x)
-#endif
-
-extern const char *debugfs_find_mountpoint(void);
-extern int debugfs_valid_mountpoint(const char *debugfs);
-extern int debugfs_valid_entry(const char *path);
-extern char *debugfs_mount(const char *mountpoint);
-extern int debugfs_umount(void);
-extern int debugfs_write(const char *entry, const char *value);
-extern int debugfs_read(const char *entry, char *buffer, size_t size);
-extern void debugfs_force_cleanup(void);
-extern int debugfs_make_path(const char *element, char *buffer, int size);
-
-#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/environment.c b/tools/perf/util/environment.c
index 275b0ee..3acdc7b 100644
--- a/tools/perf/util/environment.c
+++ b/tools/perf/util/environment.c
@@ -3,7 +3,7 @@
  * file, so that programs can link against the config parser
  * without having to link against all the rest of perf.
  */
-#include "cache.h"
+#include <util/cache.h>
 
 const char *pager_program;
 int pager_use_color = 1;
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 67eeff5..10f062c 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include <util/cache.h>
 #include "exec_cmd.h"
 #include "quote.h"
 
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1f62435..cd4a00f 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,7 +8,7 @@
 #include <linux/list.h>
 #include <linux/kernel.h>
 
-#include "util.h"
+#include <util/util.h>
 #include "header.h"
 #include "../perf.h"
 #include "trace-event.h"
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 402ac24..60325e2 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -4,7 +4,7 @@
 #include "../../../include/linux/perf_event.h"
 #include <sys/types.h>
 #include <stdbool.h>
-#include "types.h"
+#include <util/types.h>
 #include "event.h"
 
 #include <linux/bitmap.h>
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 6f2975a..cbe1c1c 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -1,8 +1,10 @@
-#include "cache.h"
+#include <util/cache.h>
+#include <linux/compiler.h>
 #include "../builtin.h"
 #include "exec_cmd.h"
 #include "levenshtein.h"
 #include "help.h"
+#include "../perf.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
 {
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index cbf7eae..4352f43 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,4 +1,4 @@
-#include "util.h"
+#include <util/util.h>
 #include "build-id.h"
 #include "hist.h"
 #include "session.h"
diff --git a/tools/perf/util/levenshtein.c b/tools/perf/util/levenshtein.c
index e521d15..68383fb 100644
--- a/tools/perf/util/levenshtein.c
+++ b/tools/perf/util/levenshtein.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include <util/cache.h>
 #include "levenshtein.h"
 
 /*
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f391345..3082109 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -6,7 +6,7 @@
 #include <linux/rbtree.h>
 #include <stdio.h>
 #include <stdbool.h>
-#include "types.h"
+#include <util/types.h>
 
 enum map_type {
 	MAP__FUNCTION = 0,
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index d54c540..e3cbe3b 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -15,7 +15,7 @@
 #include <newt.h>
 #include <sys/ttydefaults.h>
 
-#include "cache.h"
+#include <util/cache.h>
 #include "hist.h"
 #include "pstack.h"
 #include "session.h"
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
index 1915de2..2eab6a4 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include <util/cache.h>
 #include "run-command.h"
 #include "sigchain.h"
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 9bf0f40..3a22fa5 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,14 +1,14 @@
 #include "../../../include/linux/hw_breakpoint.h"
-#include "util.h"
+#include <util/util.h>
 #include "../perf.h"
 #include "parse-options.h"
 #include "parse-events.h"
 #include "exec_cmd.h"
 #include "string.h"
 #include "symbol.h"
-#include "cache.h"
+#include <util/cache.h>
 #include "header.h"
-#include "debugfs.h"
+#include <util/debugfs.h>
 
 int				nr_counters;
 
@@ -28,7 +28,7 @@ enum event_result {
 	EVT_HANDLED_ALL
 };
 
-char debugfs_path[MAXPATHLEN];
+//char debugfs_path[MAXPATHLEN];
 
 #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
 #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index fc4ab3f..473c475 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -1,5 +1,8 @@
 #ifndef __PERF_PARSE_EVENTS_H
 #define __PERF_PARSE_EVENTS_H
+
+#include "header.h"
+
 /*
  * Parse symbolic events/counts passed in as options:
  */
@@ -30,7 +33,6 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
 
 extern void print_events(void);
 
-extern char debugfs_path[];
 extern int valid_debugfs_mount(const char *debugfs);
 
 
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index 99d02aa..66e6af0 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -1,6 +1,7 @@
-#include "util.h"
+#include <util/util.h>
+#include <util/cache.h>
+#include <linux/compiler.h>
 #include "parse-options.h"
-#include "cache.h"
 
 #define OPT_SHORT 1
 #define OPT_UNSET 2
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 58a470d..e452676 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -10,7 +10,7 @@
  *
  * which is what it's designed for.
  */
-#include "cache.h"
+#include <util/cache.h>
 
 static char bad_path[] = "/bad-path/";
 /*
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 914c670..9618d2a 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -33,16 +33,16 @@
 #include <limits.h>
 
 #undef _GNU_SOURCE
-#include "util.h"
+#include <util/util.h>
 #include "event.h"
 #include "string.h"
 #include "strlist.h"
 #include "debug.h"
-#include "cache.h"
+#include <util/cache.h>
 #include "color.h"
 #include "symbol.h"
 #include "thread.h"
-#include "debugfs.h"
+#include <util/debugfs.h>
 #include "trace-event.h"	/* For __unused */
 #include "probe-event.h"
 #include "probe-finder.h"
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index d964cb1..6b1e981 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -36,7 +36,7 @@
 #include "string.h"
 #include "event.h"
 #include "debug.h"
-#include "util.h"
+#include <util/util.h>
 #include "probe-finder.h"
 
 /* Kprobe tracer basic type is up to u64 */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index e1f61dc..df19a72 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -2,7 +2,7 @@
 #define _PROBE_FINDER_H
 
 #include <stdbool.h>
-#include "util.h"
+#include <util/util.h>
 #include "probe-event.h"
 
 #define MAX_PATH_LEN		 256
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
index 13d36fa..b735ebf 100644
--- a/tools/perf/util/pstack.c
+++ b/tools/perf/util/pstack.c
@@ -4,7 +4,7 @@
  * (c) 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
  */
 
-#include "util.h"
+#include <util/util.h>
 #include "pstack.h"
 #include <linux/kernel.h>
 #include <stdlib.h>
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 01f0324..51df6c3 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include <util/cache.h>
 #include "quote.h"
 
 /* Help to copy the thing properly quoted for the shell safety.
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index da8e9b2..a139174 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -1,4 +1,4 @@
-#include "cache.h"
+#include <util/cache.h>
 #include "run-command.h"
 #include "exec_cmd.h"
 
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b059dc5..d91b9e4 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -26,7 +26,7 @@
 #include <errno.h>
 
 #include "../../perf.h"
-#include "../util.h"
+#include <util/util.h>
 #include "../trace-event.h"
 
 #include <EXTERN.h>
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 81f39ca..78b2749 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -28,7 +28,7 @@
 #include <errno.h>
 
 #include "../../perf.h"
-#include "../util.h"
+#include <util/util.h>
 #include "../trace-event.h"
 
 PyMODINIT_FUNC initperf_trace_context(void);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8f83a18..e21f759 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -9,7 +9,7 @@
 
 #include "session.h"
 #include "sort.h"
-#include "util.h"
+#include <util/util.h>
 
 static int perf_session__open(struct perf_session *self, bool force)
 {
diff --git a/tools/perf/util/sigchain.c b/tools/perf/util/sigchain.c
index ba785e9..10ca4fb 100644
--- a/tools/perf/util/sigchain.c
+++ b/tools/perf/util/sigchain.c
@@ -1,5 +1,5 @@
 #include "sigchain.h"
-#include "cache.h"
+#include <util/cache.h>
 
 #define SIGCHAIN_MAX_SIGNALS 32
 
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 0d61c40..41b2fc3 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -2,11 +2,11 @@
 #define __PERF_SORT_H
 #include "../builtin.h"
 
-#include "util.h"
+#include <util/util.h>
 
 #include "color.h"
 #include <linux/list.h>
-#include "cache.h"
+#include <util/cache.h>
 #include <linux/rbtree.h>
 #include "symbol.h"
 #include "string.h"
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
deleted file mode 100644
index 92e0685..0000000
--- a/tools/perf/util/strbuf.c
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "cache.h"
-
-int prefixcmp(const char *str, const char *prefix)
-{
-	for (; ; str++, prefix++)
-		if (!*prefix)
-			return 0;
-		else if (*str != *prefix)
-			return (unsigned char)*prefix - (unsigned char)*str;
-}
-
-/*
- * Used as the default ->buf value, so that people can always assume
- * buf is non NULL and ->buf is NUL terminated even for a freshly
- * initialized strbuf.
- */
-char strbuf_slopbuf[1];
-
-void strbuf_init(struct strbuf *sb, ssize_t hint)
-{
-	sb->alloc = sb->len = 0;
-	sb->buf = strbuf_slopbuf;
-	if (hint)
-		strbuf_grow(sb, hint);
-}
-
-void strbuf_release(struct strbuf *sb)
-{
-	if (sb->alloc) {
-		free(sb->buf);
-		strbuf_init(sb, 0);
-	}
-}
-
-char *strbuf_detach(struct strbuf *sb, size_t *sz)
-{
-	char *res = sb->alloc ? sb->buf : NULL;
-	if (sz)
-		*sz = sb->len;
-	strbuf_init(sb, 0);
-	return res;
-}
-
-void strbuf_grow(struct strbuf *sb, size_t extra)
-{
-	if (sb->len + extra + 1 <= sb->len)
-		die("you want to use way too much memory");
-	if (!sb->alloc)
-		sb->buf = NULL;
-	ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
-}
-
-static void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
-				   const void *data, size_t dlen)
-{
-	if (pos + len < pos)
-		die("you want to use way too much memory");
-	if (pos > sb->len)
-		die("`pos' is too far after the end of the buffer");
-	if (pos + len > sb->len)
-		die("`pos + len' is too far after the end of the buffer");
-
-	if (dlen >= len)
-		strbuf_grow(sb, dlen - len);
-	memmove(sb->buf + pos + dlen,
-			sb->buf + pos + len,
-			sb->len - pos - len);
-	memcpy(sb->buf + pos, data, dlen);
-	strbuf_setlen(sb, sb->len + dlen - len);
-}
-
-void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
-{
-	strbuf_splice(sb, pos, len, NULL, 0);
-}
-
-void strbuf_add(struct strbuf *sb, const void *data, size_t len)
-{
-	strbuf_grow(sb, len);
-	memcpy(sb->buf + sb->len, data, len);
-	strbuf_setlen(sb, sb->len + len);
-}
-
-void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
-{
-	int len;
-	va_list ap;
-
-	if (!strbuf_avail(sb))
-		strbuf_grow(sb, 64);
-	va_start(ap, fmt);
-	len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
-	va_end(ap);
-	if (len < 0)
-		die("your vsnprintf is broken");
-	if (len > strbuf_avail(sb)) {
-		strbuf_grow(sb, len);
-		va_start(ap, fmt);
-		len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
-		va_end(ap);
-		if (len > strbuf_avail(sb)) {
-			die("this should not happen, your snprintf is broken");
-		}
-	}
-	strbuf_setlen(sb, sb->len + len);
-}
-
-ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
-{
-	size_t oldlen = sb->len;
-	size_t oldalloc = sb->alloc;
-
-	strbuf_grow(sb, hint ? hint : 8192);
-	for (;;) {
-		ssize_t cnt;
-
-		cnt = read(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
-		if (cnt < 0) {
-			if (oldalloc == 0)
-				strbuf_release(sb);
-			else
-				strbuf_setlen(sb, oldlen);
-			return -1;
-		}
-		if (!cnt)
-			break;
-		sb->len += cnt;
-		strbuf_grow(sb, 8192);
-	}
-
-	sb->buf[sb->len] = '\0';
-	return sb->len - oldlen;
-}
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
deleted file mode 100644
index 436ac31..0000000
--- a/tools/perf/util/strbuf.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef __PERF_STRBUF_H
-#define __PERF_STRBUF_H
-
-/*
- * Strbuf's can be use in many ways: as a byte array, or to store arbitrary
- * long, overflow safe strings.
- *
- * Strbufs has some invariants that are very important to keep in mind:
- *
- * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to
- *    build complex strings/buffers whose final size isn't easily known.
- *
- *    It is NOT legal to copy the ->buf pointer away.
- *    `strbuf_detach' is the operation that detachs a buffer from its shell
- *    while keeping the shell valid wrt its invariants.
- *
- * 2. the ->buf member is a byte array that has at least ->len + 1 bytes
- *    allocated. The extra byte is used to store a '\0', allowing the ->buf
- *    member to be a valid C-string. Every strbuf function ensure this
- *    invariant is preserved.
- *
- *    Note that it is OK to "play" with the buffer directly if you work it
- *    that way:
- *
- *    strbuf_grow(sb, SOME_SIZE);
- *       ... Here, the memory array starting at sb->buf, and of length
- *       ... strbuf_avail(sb) is all yours, and you are sure that
- *       ... strbuf_avail(sb) is at least SOME_SIZE.
- *    strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE);
- *
- *    Of course, SOME_OTHER_SIZE must be smaller or equal to strbuf_avail(sb).
- *
- *    Doing so is safe, though if it has to be done in many places, adding the
- *    missing API to the strbuf module is the way to go.
- *
- *    XXX: do _not_ assume that the area that is yours is of size ->alloc - 1
- *         even if it's true in the current implementation. Alloc is somehow a
- *         "private" member that should not be messed with.
- */
-
-#include <assert.h>
-
-extern char strbuf_slopbuf[];
-struct strbuf {
-	size_t alloc;
-	size_t len;
-	char *buf;
-};
-
-#define STRBUF_INIT  { 0, 0, strbuf_slopbuf }
-
-/*----- strbuf life cycle -----*/
-extern void strbuf_init(struct strbuf *buf, ssize_t hint);
-extern void strbuf_release(struct strbuf *);
-extern char *strbuf_detach(struct strbuf *, size_t *);
-
-/*----- strbuf size related -----*/
-static inline ssize_t strbuf_avail(const struct strbuf *sb) {
-	return sb->alloc ? sb->alloc - sb->len - 1 : 0;
-}
-
-extern void strbuf_grow(struct strbuf *, size_t);
-
-static inline void strbuf_setlen(struct strbuf *sb, size_t len) {
-	if (!sb->alloc)
-		strbuf_grow(sb, 0);
-	assert(len < sb->alloc);
-	sb->len = len;
-	sb->buf[len] = '\0';
-}
-
-/*----- add data in your buffer -----*/
-static inline void strbuf_addch(struct strbuf *sb, int c) {
-	strbuf_grow(sb, 1);
-	sb->buf[sb->len++] = c;
-	sb->buf[sb->len] = '\0';
-}
-
-extern void strbuf_remove(struct strbuf *, size_t pos, size_t len);
-
-extern void strbuf_add(struct strbuf *, const void *, size_t);
-static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
-	strbuf_add(sb, s, strlen(s));
-}
-
-__attribute__((format(printf,2,3)))
-extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
-
-/* XXX: if read fails, any partial read is undone */
-extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
-
-#endif /* __PERF_STRBUF_H */
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 0409fc7..b5edba7 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -1,4 +1,4 @@
-#include "util.h"
+#include <util/util.h>
 #include "string.h"
 
 #define K 1024LL
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h
index e078198..278a72d 100644
--- a/tools/perf/util/svghelper.h
+++ b/tools/perf/util/svghelper.h
@@ -1,7 +1,7 @@
 #ifndef __PERF_SVGHELPER_H
 #define __PERF_SVGHELPER_H
 
-#include "types.h"
+#include <util/types.h>
 
 extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
 extern void svg_box(int Yslot, u64 start, u64 end, const char *type);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 1f7ecd4..ce885bc 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -4,7 +4,7 @@
 #include <string.h>
 #include "session.h"
 #include "thread.h"
-#include "util.h"
+#include <util/util.h>
 #include "debug.h"
 
 int find_all_tid(int pid, pid_t ** all_tid)
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index b157260..6bdf4a1 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -38,7 +38,7 @@
 
 #include "../perf.h"
 #include "trace-event.h"
-#include "debugfs.h"
+#include <util/debugfs.h>
 
 #define VERSION "0.5"
 
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 73a0222..dcecf73 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -30,7 +30,7 @@
 
 #undef _GNU_SOURCE
 #include "../perf.h"
-#include "util.h"
+#include <util/util.h>
 #include "trace-event.h"
 
 int header_page_ts_offset;
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index f55cc3a..c5c62b1 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -37,7 +37,7 @@
 #include <errno.h>
 
 #include "../perf.h"
-#include "util.h"
+#include <util/util.h>
 #include "trace-event.h"
 
 static int input_fd;
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 7ea983a..d5eaffa 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -26,7 +26,7 @@
 #include <errno.h>
 
 #include "../perf.h"
-#include "util.h"
+#include <util/util.h>
 #include "trace-event.h"
 
 struct scripting_context *scripting_context;
diff --git a/tools/perf/util/types.h b/tools/perf/util/types.h
deleted file mode 100644
index 7d6b833..0000000
--- a/tools/perf/util/types.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __PERF_TYPES_H
-#define __PERF_TYPES_H
-
-/*
- * We define u64 as unsigned long long for every architecture
- * so that we can print it with %Lx without getting warnings.
- */
-typedef unsigned long long u64;
-typedef signed long long   s64;
-typedef unsigned int	   u32;
-typedef signed int	   s32;
-typedef unsigned short	   u16;
-typedef signed short	   s16;
-typedef unsigned char	   u8;
-typedef signed char	   s8;
-
-#endif /* __PERF_TYPES_H */
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index e16bf9a..7085b6f 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) Linus Torvalds, 2005
  */
-#include "util.h"
+#include <util/util.h>
 
 static void report(const char *prefix, const char *err, va_list params)
 {
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 2142656..8714309 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,4 +1,4 @@
-#include "util.h"
+#include <util/util.h>
 #include <sys/mman.h>
 
 int mkdir_p(char *path, mode_t mode)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
deleted file mode 100644
index 4e8b6b0..0000000
--- a/tools/perf/util/util.h
+++ /dev/null
@@ -1,282 +0,0 @@
-#ifndef GIT_COMPAT_UTIL_H
-#define GIT_COMPAT_UTIL_H
-
-#define _FILE_OFFSET_BITS 64
-
-#ifndef FLEX_ARRAY
-/*
- * See if our compiler is known to support flexible array members.
- */
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-# define FLEX_ARRAY /* empty */
-#elif defined(__GNUC__)
-# if (__GNUC__ >= 3)
-#  define FLEX_ARRAY /* empty */
-# else
-#  define FLEX_ARRAY 0 /* older GNU extension */
-# endif
-#endif
-
-/*
- * Otherwise, default to safer but a bit wasteful traditional style
- */
-#ifndef FLEX_ARRAY
-# define FLEX_ARRAY 1
-#endif
-#endif
-
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-
-#ifdef __GNUC__
-#define TYPEOF(x) (__typeof__(x))
-#else
-#define TYPEOF(x)
-#endif
-
-#define MSB(x, bits) ((x) & TYPEOF(x)(~0ULL << (sizeof(x) * 8 - (bits))))
-#define HAS_MULTI_BITS(i)  ((i) & ((i) - 1))  /* checks if an integer has more than 1 bit set */
-
-/* Approximation of the length of the decimal representation of this type. */
-#define decimal_length(x)	((int)(sizeof(x) * 2.56 + 0.5) + 1)
-
-#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
-#define _BSD_SOURCE 1
-#define HAS_BOOL
-
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/time.h>
-#include <time.h>
-#include <signal.h>
-#include <fnmatch.h>
-#include <assert.h>
-#include <regex.h>
-#include <utime.h>
-#include <sys/wait.h>
-#include <sys/poll.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pwd.h>
-#include <inttypes.h>
-#include "../../../include/linux/magic.h"
-#include "types.h"
-#include <sys/ttydefaults.h>
-
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
-extern const char *graph_line;
-extern const char *graph_dotted_line;
-
-/* On most systems <limits.h> would have given us this, but
- * not on some systems (e.g. GNU/Hurd).
- */
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-#ifndef PRIuMAX
-#define PRIuMAX "llu"
-#endif
-
-#ifndef PRIu32
-#define PRIu32 "u"
-#endif
-
-#ifndef PRIx32
-#define PRIx32 "x"
-#endif
-
-#ifndef PATH_SEP
-#define PATH_SEP ':'
-#endif
-
-#ifndef STRIP_EXTENSION
-#define STRIP_EXTENSION ""
-#endif
-
-#ifndef has_dos_drive_prefix
-#define has_dos_drive_prefix(path) 0
-#endif
-
-#ifndef is_dir_sep
-#define is_dir_sep(c) ((c) == '/')
-#endif
-
-#ifdef __GNUC__
-#define NORETURN __attribute__((__noreturn__))
-#else
-#define NORETURN
-#ifndef __attribute__
-#define __attribute__(x)
-#endif
-#endif
-
-/* General helper functions */
-extern void usage(const char *err) NORETURN;
-extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
-extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
-extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
-
-#include "../../../include/linux/stringify.h"
-
-#define DIE_IF(cnd)	\
-	do { if (cnd)	\
-		die(" at (" __FILE__ ":" __stringify(__LINE__) "): "	\
-		    __stringify(cnd) "\n");				\
-	} while (0)
-
-
-extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
-
-extern int prefixcmp(const char *str, const char *prefix);
-
-static inline const char *skip_prefix(const char *str, const char *prefix)
-{
-	size_t len = strlen(prefix);
-	return strncmp(str, prefix, len) ? NULL : str + len;
-}
-
-#ifdef __GLIBC_PREREQ
-#if __GLIBC_PREREQ(2, 1)
-#define HAVE_STRCHRNUL
-#endif
-#endif
-
-#ifndef HAVE_STRCHRNUL
-#define strchrnul gitstrchrnul
-static inline char *gitstrchrnul(const char *s, int c)
-{
-	while (*s && *s != c)
-		s++;
-	return (char *)s;
-}
-#endif
-
-/*
- * Wrappers:
- */
-extern char *xstrdup(const char *str);
-extern void *xrealloc(void *ptr, size_t size) __attribute__((weak));
-
-
-static inline void *zalloc(size_t size)
-{
-	return calloc(1, size);
-}
-
-static inline int has_extension(const char *filename, const char *ext)
-{
-	size_t len = strlen(filename);
-	size_t extlen = strlen(ext);
-
-	return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
-}
-
-/* Sane ctype - no locale, and works with signed chars */
-#undef isascii
-#undef isspace
-#undef isdigit
-#undef isxdigit
-#undef isalpha
-#undef isprint
-#undef isalnum
-#undef tolower
-#undef toupper
-
-extern unsigned char sane_ctype[256];
-#define GIT_SPACE		0x01
-#define GIT_DIGIT		0x02
-#define GIT_ALPHA		0x04
-#define GIT_GLOB_SPECIAL	0x08
-#define GIT_REGEX_SPECIAL	0x10
-#define GIT_PRINT_EXTRA		0x20
-#define GIT_PRINT		0x3E
-#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0)
-#define isascii(x) (((x) & ~0x7f) == 0)
-#define isspace(x) sane_istest(x,GIT_SPACE)
-#define isdigit(x) sane_istest(x,GIT_DIGIT)
-#define isxdigit(x)	\
-	(sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
-#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 tolower(x) sane_case((unsigned char)(x), 0x20)
-#define toupper(x) sane_case((unsigned char)(x), 0)
-
-static inline int sane_case(int x, int high)
-{
-	if (sane_istest(x, GIT_ALPHA))
-		x = (x & ~0x20) | high;
-	return x;
-}
-
-#ifndef DIR_HAS_BSD_GROUP_SEMANTICS
-# define FORCE_DIR_SET_GID S_ISGID
-#else
-# define FORCE_DIR_SET_GID 0
-#endif
-
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
-int mkdir_p(char *path, mode_t mode);
-int copyfile(const char *from, const char *to);
-
-s64 perf_atoll(const char *str);
-char **argv_split(const char *str, int *argcp);
-void argv_free(char **argv);
-bool strglobmatch(const char *str, const char *pat);
-bool strlazymatch(const char *str, const char *pat);
-unsigned long convert_unit(unsigned long value, char *unit);
-
-#ifndef ESC
-#define ESC 27
-#endif
-
-static inline bool is_exit_key(int key)
-{
-	char up;
-	if (key == CTRL('c') || key == ESC)
-		return true;
-	up = toupper(key);
-	return up == 'Q';
-}
-
-#define _STR(x) #x
-#define STR(x) _STR(x)
-
-#endif
diff --git a/tools/perf/util/values.c b/tools/perf/util/values.c
index cfa55d6..e25c4b4 100644
--- a/tools/perf/util/values.c
+++ b/tools/perf/util/values.c
@@ -1,6 +1,6 @@
 #include <stdlib.h>
 
-#include "util.h"
+#include <util/util.h>
 #include "values.h"
 
 void perf_read_values_init(struct perf_read_values *values)
diff --git a/tools/perf/util/values.h b/tools/perf/util/values.h
index 2fa967e..012bc12 100644
--- a/tools/perf/util/values.h
+++ b/tools/perf/util/values.h
@@ -1,7 +1,7 @@
 #ifndef __PERF_VALUES_H
 #define __PERF_VALUES_H
 
-#include "types.h"
+#include <util/types.h>
 
 struct perf_read_values {
 	int threads;
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
index 73e900e..3addc76 100644
--- a/tools/perf/util/wrapper.c
+++ b/tools/perf/util/wrapper.c
@@ -1,7 +1,8 @@
 /*
  * Various trivial helper wrappers around standard functions
  */
-#include "cache.h"
+#include <linux/compiler.h>
+#include <util/cache.h>
 
 /*
  * There's no pack memory to release - but stay close to the Git
-- 
1.6.4.4


-- 
Regards/Gruss,
Boris.

Operating Systems Research Center
Advanced Micro Devices, Inc.

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-14 19:25                             ` Borislav Petkov
@ 2010-06-14 21:01                               ` Arnaldo Carvalho de Melo
  2010-06-14 21:24                                 ` Borislav Petkov
  0 siblings, 1 reply; 31+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-06-14 21:01 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Peter Zijlstra, Ingo Molnar, Borislav Petkov,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

Em Mon, Jun 14, 2010 at 09:25:14PM +0200, Borislav Petkov escreveu:
> From: Arnaldo Carvalho de Melo <acme@infradead.org>
> Date: Thu, Jun 03, 2010 at 02:32:42PM -0300
> 
> > Right, that has to be done, I have sample code I want to put in samples/
> > to show how to use the symbol libraries in tools/perf/util/, will take a
> > stab at moving things for tools/lib/.
> > 
> > We'll need a top level Makefile, I guess, so that when asking to build
> > tools/perf, it notices that it has to build tools/lib/, etc.
> > 
> > Probably we'll need tools/lib/symbols/, tools/lib/trace/parser/ things
> > like that, I'll start with the symbols part, using a samples/ file I
> > already wrote.
> 
> Right, so I started playing with this, added a global Makefile to tools/
> and from there we descend into lib/ and perf/ in that order to prepare
> all the modules for the perflib. I've played with the include paths so
> that you can have #include <util/util.h> for all that generic library
> stuff.
> 
> The patch below carves out the debugfs helpers along with some generic
> headers, please take a look and let me know if this is an agreeable
> direction I'm going. Yeah, it is big, I think vger won't be able to
> swallow it but this is only moving files around so...

One thing I thought was that perhaps reusing Kbuild would be a good
idea, something like:

cd tools/
make menuconfig

And use all the Kbuild machinery to select needed features, etc.

What do you think?

It can be a follow up to what you're doing, that is needed anyway, some
questions below:
 
> Thanks.
> 
> --
> >From 0f391f0acf39d3b2e85145dce389cbf425cb7cdd Mon Sep 17 00:00:00 2001
> From: Borislav Petkov <borislav.petkov@amd.com>
> Date: Mon, 14 Jun 2010 21:14:15 +0200
> Subject: [PATCH] perf: rewire generic library stuff
> 
> ---
>  tools/Makefile                                     |   74 +++++
>  tools/lib/Makefile                                 |   41 +++
>  tools/lib/util/cache.h                             |   86 ++++++
>  tools/lib/util/debugfs.c                           |  252 +++++++++++++++++
>  tools/lib/util/debugfs.h                           |   31 +++
>  tools/lib/util/strbuf.c                            |  133 +++++++++
>  tools/lib/util/strbuf.h                            |   92 +++++++
>  tools/lib/util/types.h                             |   17 ++
>  tools/lib/util/util.h                              |  282 ++++++++++++++++++++

Will we continue using "util" here? What other name could we pick? Nah,
probably for the ones you moved we can continue using it, the symbols
part I plan to move to tools/lib/symbol/.

>  tools/perf/Makefile                                |   64 +----
>  tools/perf/bench/bench.h                           |    2 +
>  tools/perf/bench/mem-memcpy.c                      |    2 +-
>  tools/perf/bench/sched-messaging.c                 |    2 +-
>  tools/perf/bench/sched-pipe.c                      |    2 +-
>  tools/perf/builtin-bench.c                         |    2 +-
>  tools/perf/builtin.h                               |    4 +-

> -#include "types.h"
> +#include <util/types.h>

I thought about suggesting using -I to reduce patch size, but then it is
using "" :-\

So I'll do some testing here and merge this for .36 unless somebody has
other issues with this, Ingo? Frédéric?

- Arnaldo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-14 21:01                               ` Arnaldo Carvalho de Melo
@ 2010-06-14 21:24                                 ` Borislav Petkov
  2010-06-15  1:02                                   ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-06-14 21:24 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

From: Arnaldo Carvalho de Melo <acme@infradead.org>
Date: Mon, Jun 14, 2010 at 06:01:16PM -0300

> > Right, so I started playing with this, added a global Makefile to tools/
> > and from there we descend into lib/ and perf/ in that order to prepare
> > all the modules for the perflib. I've played with the include paths so
> > that you can have #include <util/util.h> for all that generic library
> > stuff.
> > 
> > The patch below carves out the debugfs helpers along with some generic
> > headers, please take a look and let me know if this is an agreeable
> > direction I'm going. Yeah, it is big, I think vger won't be able to
> > swallow it but this is only moving files around so...
> 
> One thing I thought was that perhaps reusing Kbuild would be a good
> idea, something like:
> 
> cd tools/
> make menuconfig
> 
> And use all the Kbuild machinery to select needed features, etc.
> 
> What do you think?

Why not, however, do we need it at this point? I mean, you simply do

make -j; make install

in tools/perf/ and all is good. It even tells you if some libraries are
missing. I simply don't see such a large amount of options to justify
a configurator but maybe there are usecases where Kconfig would make
sense, hmmm?

> It can be a follow up to what you're doing, that is needed anyway, some
> questions below:
>  
> > Thanks.
> > 
> > --
> > >From 0f391f0acf39d3b2e85145dce389cbf425cb7cdd Mon Sep 17 00:00:00 2001
> > From: Borislav Petkov <borislav.petkov@amd.com>
> > Date: Mon, 14 Jun 2010 21:14:15 +0200
> > Subject: [PATCH] perf: rewire generic library stuff
> > 
> > ---
> >  tools/Makefile                                     |   74 +++++
> >  tools/lib/Makefile                                 |   41 +++
> >  tools/lib/util/cache.h                             |   86 ++++++
> >  tools/lib/util/debugfs.c                           |  252 +++++++++++++++++
> >  tools/lib/util/debugfs.h                           |   31 +++
> >  tools/lib/util/strbuf.c                            |  133 +++++++++
> >  tools/lib/util/strbuf.h                            |   92 +++++++
> >  tools/lib/util/types.h                             |   17 ++
> >  tools/lib/util/util.h                              |  282 ++++++++++++++++++++
> 
> Will we continue using "util" here? What other name could we pick? Nah,
> probably for the ones you moved we can continue using it, the symbols
> part I plan to move to tools/lib/symbol/.

Yeah, names are kinda arbitrary. Keeping "util" meant as little changes
as possible but it would make more sense to simply have all different
library modules under "tools/lib/<module>.(c|h)" Will do so in the next
version.

> >  tools/perf/Makefile                                |   64 +----
> >  tools/perf/bench/bench.h                           |    2 +
> >  tools/perf/bench/mem-memcpy.c                      |    2 +-
> >  tools/perf/bench/sched-messaging.c                 |    2 +-
> >  tools/perf/bench/sched-pipe.c                      |    2 +-
> >  tools/perf/builtin-bench.c                         |    2 +-
> >  tools/perf/builtin.h                               |    4 +-
> 
> > -#include "types.h"
> > +#include <util/types.h>
> 
> I thought about suggesting using -I to reduce patch size, but then it is
> using "" :-\

Yeah, I have the -I$(CURDIR)/lib for this in the top level Makefile so all
library includes would be like:

#include <util.h>

however, this does not differentiate perflib (let's call it that for how
:) from libc headers. Do we want a "perf" or "kernel" or "perflib" or
whatever prefix here - it might make sense later when this thing grows
to differentiate between the namespaces...?

> So I'll do some testing here and merge this for .36 unless somebody has
> other issues with this, Ingo? Frédéric?

Can you please wait a bit with the merging, I'd like to write the
whole rasd daemon stuff before we merge that and have the generic lib
carve-out in one patchset?

Thanks.

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-14 21:24                                 ` Borislav Petkov
@ 2010-06-15  1:02                                   ` Arnaldo Carvalho de Melo
  2010-06-15 10:22                                     ` Borislav Petkov
  2010-06-17 13:43                                     ` Borislav Petkov
  0 siblings, 2 replies; 31+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-06-15  1:02 UTC (permalink / raw)
  To: Borislav Petkov, Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

Em Mon, Jun 14, 2010 at 11:24:26PM +0200, Borislav Petkov escreveu:
> From: Arnaldo Carvalho de Melo <acme@infradead.org>
> > One thing I thought was that perhaps reusing Kbuild would be a good
> > idea, something like:
> > 
> > cd tools/
> > make menuconfig
> > 
> > And use all the Kbuild machinery to select needed features, etc.
> > 
> > What do you think?
> 
> Why not, however, do we need it at this point? I mean, you simply do
> 
> make -j; make install
> 
> in tools/perf/ and all is good. It even tells you if some libraries are
> missing. I simply don't see such a large amount of options to justify
> a configurator but maybe there are usecases where Kconfig would make
> sense, hmmm?

Yeah, I mean longer term, as we get libraries separated, more benchmarks,
tools, etc.
 
> > It can be a follow up to what you're doing, that is needed anyway, some
> > questions below:

> > >  tools/lib/util/util.h                              |  282 ++++++++++++++++++++
> > 
> > Will we continue using "util" here? What other name could we pick? Nah,
> > probably for the ones you moved we can continue using it, the symbols
> > part I plan to move to tools/lib/symbol/.
 
> Yeah, names are kinda arbitrary. Keeping "util" meant as little changes as
> possible but it would make more sense to simply have all different library
> modules under "tools/lib/<module>.(c|h)" Will do so in the next version.

Ok

> > >  tools/perf/builtin-bench.c                         |    2 +-
> > >  tools/perf/builtin.h                               |    4 +-
> > 
> > > -#include "types.h"
> > > +#include <util/types.h>
> > 
> > I thought about suggesting using -I to reduce patch size, but then it is
> > using "" :-\
> 
> Yeah, I have the -I$(CURDIR)/lib for this in the top level Makefile so all
> library includes would be like:
> 
> #include <util.h>
> 
> however, this does not differentiate perflib (let's call it that for how
> :) from libc headers. Do we want a "perf" or "kernel" or "perflib" or
> whatever prefix here - it might make sense later when this thing grows
> to differentiate between the namespaces...?

Agreed, but the last name this thing will have will be 'perf'something :-)

One of the goals at least I have with pursuing this path is to separate
out everything that is not strictly 'perf' into things that can be reused
by other tools, like yours.
 
> > So I'll do some testing here and merge this for .36 unless somebody has
> > other issues with this, Ingo? Frédéric?

> Can you please wait a bit with the merging, I'd like to write the
> whole rasd daemon stuff before we merge that and have the generic lib
> carve-out in one patchset?

Ok with me, I'll see if I manage to do the symbols part tho, as it is
kinda self contained and I already toyed with writing a test program
that uses the subset of tools/perf/util/ that deals with symbols.

Part of that experiment is in tools/perf/builtin-test.c, parts are
exemplified by this Makefile:

[acme@doppio linux-2.6-tip]$ cat tools/perf/util/examples/symbol/Makefile 
ppio linux-2.6-tip]$ l tools/perf/util/examples/symbol/Makefile 
-rw-rw-r-- 1 acme acme 693 2010-03-27 11:14 tools/perf/util/examples/symbol/Makefile
CFLAGS = -Wall -I../../include -I../.. -std=gnu99 -DNO_DEMANGLE -g
LDFLAGS = -lelf

ifeq ("$(origin O)", "command line")
	OUTPUT := $(O)/
endif

LIBSYM_OBJS = $(OUTPUT)map.o $(OUTPUT)rbtree.o $(OUTPUT)symbol.o $(OUTPUT)strlist.o $(OUTPUT)eprintf.o

all: $(OUTPUT)dsym $(OUTPUT)ksym

$(OUTPUT)dsym: $(OUTPUT)dsym.o $(LIBSYM_OBJS)
	gcc -o $@ $(LDFLAGS) $@.o $(LIBSYM_OBJS)

$(OUTPUT)ksym: $(OUTPUT)ksym.o $(LIBSYM_OBJS)
	gcc -o $@ $(LDFLAGS) $@.o $(LIBSYM_OBJS)

$(OUTPUT)rbtree.o: ../../../../../lib/rbtree.c
	gcc -o $@ -c $(CFLAGS) $<

$(OUTPUT)%.o: ../../%.c
	gcc -o $@ -c $(CFLAGS) $<

$(OUTPUT)%.o: %.c
	gcc -o $@ -c $(CFLAGS) $<

clean:
	rm -f $(LIBSYM_OBJS) $(OUTPUT)?sym.o $(OUTPUT)?sym
[acme@doppio linux-2.6-tip]$
[acme@doppio linux-2.6-tip]$ cd tools/perf/util/examples/symbol/
[acme@doppio symbol]$ l build/
total 104
drwxrwxr-x 2 acme acme  4096 2010-06-14 21:55 ./
drwxrwxr-x 3 acme acme  4096 2010-03-28 13:52 ../
-rwxrwxr-x 1 acme acme 47040 2010-06-14 21:55 dsym*
-rwxrwxr-x 1 acme acme 47200 2010-06-14 21:55 ksym*
[acme@doppio symbol]$ ldd build/dsym
	linux-vdso.so.1 =>  (0x00007fffe6cf2000)
	libelf.so.1 => /usr/lib64/libelf.so.1 (0x0000003404c00000)
	libc.so.6 => /lib64/libc.so.6 (0x0000003715a00000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003715600000)
[acme@doppio symbol]$
[acme@doppio symbol]$ build/dsym 
usage: dso DSO_NAME SYMBOL_NAME|0xADDR
[acme@doppio symbol]$ build/dsym /lib/libc-2.10.2.so malloc
malloc: 0x749c0-0x74bee
[acme@doppio symbol]$ build/dsym /lib/libc-2.10.2.so 0x749ee
__GI___libc_malloc: 0x749c0-0x74bee
[acme@doppio symbol]$ build/dsym /lib/libc-2.10.2.so __GI___libc_malloc
__GI___libc_malloc: 0x749c0-0x74bee

:-)

- Arnaldo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-15  1:02                                   ` Arnaldo Carvalho de Melo
@ 2010-06-15 10:22                                     ` Borislav Petkov
  2010-06-15 13:22                                       ` Arnaldo Carvalho de Melo
  2010-06-17 13:43                                     ` Borislav Petkov
  1 sibling, 1 reply; 31+ messages in thread
From: Borislav Petkov @ 2010-06-15 10:22 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

From: Arnaldo Carvalho de Melo <acme@infradead.org>
Date: Mon, Jun 14, 2010 at 09:02:01PM -0400

> Em Mon, Jun 14, 2010 at 11:24:26PM +0200, Borislav Petkov escreveu:
> > From: Arnaldo Carvalho de Melo <acme@infradead.org>
> > > One thing I thought was that perhaps reusing Kbuild would be a good
> > > idea, something like:
> > > 
> > > cd tools/
> > > make menuconfig
> > > 
> > > And use all the Kbuild machinery to select needed features, etc.
> > > 
> > > What do you think?
> > 
> > Why not, however, do we need it at this point? I mean, you simply do
> > 
> > make -j; make install
> > 
> > in tools/perf/ and all is good. It even tells you if some libraries are
> > missing. I simply don't see such a large amount of options to justify
> > a configurator but maybe there are usecases where Kconfig would make
> > sense, hmmm?
> 
> Yeah, I mean longer term, as we get libraries separated, more benchmarks,
> tools, etc.

Sure, this is generally a good idea.

>  
> > > It can be a follow up to what you're doing, that is needed anyway, some
> > > questions below:
> 
> > > >  tools/lib/util/util.h                              |  282 ++++++++++++++++++++
> > > 
> > > Will we continue using "util" here? What other name could we pick? Nah,
> > > probably for the ones you moved we can continue using it, the symbols
> > > part I plan to move to tools/lib/symbol/.
>  
> > Yeah, names are kinda arbitrary. Keeping "util" meant as little changes as
> > possible but it would make more sense to simply have all different library
> > modules under "tools/lib/<module>.(c|h)" Will do so in the next version.
> 
> Ok
> 
> > > >  tools/perf/builtin-bench.c                         |    2 +-
> > > >  tools/perf/builtin.h                               |    4 +-
> > > 
> > > > -#include "types.h"
> > > > +#include <util/types.h>
> > > 
> > > I thought about suggesting using -I to reduce patch size, but then it is
> > > using "" :-\
> > 
> > Yeah, I have the -I$(CURDIR)/lib for this in the top level Makefile so all
> > library includes would be like:
> > 
> > #include <util.h>
> > 
> > however, this does not differentiate perflib (let's call it that for how
> > :) from libc headers. Do we want a "perf" or "kernel" or "perflib" or
> > whatever prefix here - it might make sense later when this thing grows
> > to differentiate between the namespaces...?
> 
> Agreed, but the last name this thing will have will be 'perf'something :-)
> 
> One of the goals at least I have with pursuing this path is to separate
> out everything that is not strictly 'perf' into things that can be reused
> by other tools, like yours.

Ok, since I'm a big fan of unambiguous short names, let's call it "lk"
for "linux kernel" and have this namespace for all generic headers. So
when you include those, you have something like

#include <lk/util.h>

How does that sound?

> > > So I'll do some testing here and merge this for .36 unless somebody has
> > > other issues with this, Ingo? Frédéric?
> 
> > Can you please wait a bit with the merging, I'd like to write the
> > whole rasd daemon stuff before we merge that and have the generic lib
> > carve-out in one patchset?
> 
> Ok with me, I'll see if I manage to do the symbols part tho, as it is
> kinda self contained and I already toyed with writing a test program
> that uses the subset of tools/perf/util/ that deals with symbols.

Neat, let's sync when I got my stuff ready so that we merge it together
and fixup any paths fallout that might happen.

Thanks.

-- 
Regards/Gruss,
Boris.

Operating Systems Research Center
Advanced Micro Devices, Inc.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-15 10:22                                     ` Borislav Petkov
@ 2010-06-15 13:22                                       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 31+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-06-15 13:22 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, H. Peter Anvin,
	linux-kernel

Em Tue, Jun 15, 2010 at 12:22:59PM +0200, Borislav Petkov escreveu:
> From: Arnaldo Carvalho de Melo <acme@infradead.org>
> Date: Mon, Jun 14, 2010 at 09:02:01PM -0400
> 
> > Em Mon, Jun 14, 2010 at 11:24:26PM +0200, Borislav Petkov escreveu:
> > > From: Arnaldo Carvalho de Melo <acme@infradead.org>
> > > > From: Arnaldo Carvalho de Melo <acme@infradead.org>
> > > > Will we continue using "util" here? What other name could we pick? Nah,
> > > > probably for the ones you moved we can continue using it, the symbols
> > > > part I plan to move to tools/lib/symbol/.
> > > Em Mon, Jun 14, 2010 at 11:24:26PM +0200, Borislav Petkov escreveu:
> > > Yeah, names are kinda arbitrary. Keeping "util" meant as little changes as
> > > possible but it would make more sense to simply have all different library
> > > modules under "tools/lib/<module>.(c|h)" Will do so in the next version.
> > 
> > Ok
> > 
> > > > >  tools/perf/builtin-bench.c                         |    2 +-
> > > > >  tools/perf/builtin.h                               |    4 +-
> > > > 
> > > > > -#include "types.h"
> > > > > +#include <util/types.h>
> > > > 
> > > > I thought about suggesting using -I to reduce patch size, but then it is
> > > > using "" :-\
> > > 
> > > Yeah, I have the -I$(CURDIR)/lib for this in the top level Makefile so all
> > > library includes would be like:
> > > 
> > > #include <util.h>
> > > 
> > > however, this does not differentiate perflib (let's call it that for how
> > > :) from libc headers. Do we want a "perf" or "kernel" or "perflib" or
> > > whatever prefix here - it might make sense later when this thing grows
> > > to differentiate between the namespaces...?
> > 
> > Agreed, but the last name this thing will have will be 'perf'something :-)
> > 
> > One of the goals at least I have with pursuing this path is to separate
> > out everything that is not strictly 'perf' into things that can be reused
> > by other tools, like yours.
> 
> Ok, since I'm a big fan of unambiguous short names, let's call it "lk"
> for "linux kernel" and have this namespace for all generic headers. So
> when you include those, you have something like
> 
> #include <lk/util.h>
> 
> How does that sound?

As this code originated on the Linux kernel, should be OK and probably
unused.

Peter, ideas?

- Arnaldo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-15  1:02                                   ` Arnaldo Carvalho de Melo
  2010-06-15 10:22                                     ` Borislav Petkov
@ 2010-06-17 13:43                                     ` Borislav Petkov
  2010-06-17 14:25                                       ` Arnaldo Carvalho de Melo
  2010-06-17 16:19                                       ` Steven Rostedt
  1 sibling, 2 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-06-17 13:43 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

From: Arnaldo Carvalho de Melo <acme@infradead.org>
Date: Mon, Jun 14, 2010 at 10:02:01PM -0300

> > > I thought about suggesting using -I to reduce patch size, but then it is
> > > using "" :-\
> > 
> > Yeah, I have the -I$(CURDIR)/lib for this in the top level Makefile so all
> > library includes would be like:
> > 
> > #include <util.h>
> > 
> > however, this does not differentiate perflib (let's call it that for how
> > :) from libc headers. Do we want a "perf" or "kernel" or "perflib" or
> > whatever prefix here - it might make sense later when this thing grows
> > to differentiate between the namespaces...?
> 
> Agreed, but the last name this thing will have will be 'perf'something :-)
> 
> One of the goals at least I have with pursuing this path is to separate
> out everything that is not strictly 'perf' into things that can be reused
> by other tools, like yours.

I'm still splitting perf/util into a more or less generic lib.
Now, I want to reuse as much code as possible and am parsing
the "mce:mce_record" tracepoint using parse_events(). However,
this means that I have to push the not-so-generic perf bits
like util/parse-events.c into the lib. Which, in turn, pulls in
util/trace-event* etc.

What is your preference, do we want to export all perf/util stuff for
other tools to use or rather link other tools together with compilation
modules from perf/util in case those other tools need them?

I'm leaning towards the first one and am thinking "maximize code reuse"
but I'm not completely sure, there might be reasons against it...

Hmm...?

-- 
Regards/Gruss,
Boris.

Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Gemeinde Aschheim, Landkreis München
Registergericht Muenchen, HRB Nr. 43632

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-17 13:43                                     ` Borislav Petkov
@ 2010-06-17 14:25                                       ` Arnaldo Carvalho de Melo
  2010-06-17 15:27                                         ` Borislav Petkov
  2010-06-17 16:19                                       ` Steven Rostedt
  1 sibling, 1 reply; 31+ messages in thread
From: Arnaldo Carvalho de Melo @ 2010-06-17 14:25 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

Em Thu, Jun 17, 2010 at 03:43:57PM +0200, Borislav Petkov escreveu:
> From: Arnaldo Carvalho de Melo <acme@infradead.org>
> Date: Mon, Jun 14, 2010 at 10:02:01PM -0300
> > > however, this does not differentiate perflib (let's call it that for how
> > > :) from libc headers. Do we want a "perf" or "kernel" or "perflib" or
> > > whatever prefix here - it might make sense later when this thing grows
> > > to differentiate between the namespaces...?

> > Agreed, but the last name this thing will have will be 'perf'something :-)
> > One of the goals at least I have with pursuing this path is to separate
> > out everything that is not strictly 'perf' into things that can be reused
> > by other tools, like yours.

> I'm still splitting perf/util into a more or less generic lib.  Now, I
> want to reuse as much code as possible and am parsing the
> "mce:mce_record" tracepoint using parse_events(). However, this means
> that I have to push the not-so-generic perf bits like
> util/parse-events.c into the lib. Which, in turn, pulls in
> util/trace-event* etc.

I'm not that familiar with the trace bits in perf, but I'd say pick what
is needed for your tool and stash it into files in a tools/lib/trace/
directory, in a way that can be used by both perf and your tools.

I.e. no need to move files as-is, you can reorganize things to make it
useful for both perf and your tool.
 
> What is your preference, do we want to export all perf/util stuff for
> other tools to use or rather link other tools together with
> compilation modules from perf/util in case those other tools need
> them?

If we do it on a as-needed basis, as I suggested, we go eroding the
current perf hodgepodge of potentially generic stuff.
 
> I'm leaning towards the first one and am thinking "maximize code reuse"
> but I'm not completely sure, there might be reasons against it...

- Arnaldo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-17 14:25                                       ` Arnaldo Carvalho de Melo
@ 2010-06-17 15:27                                         ` Borislav Petkov
  0 siblings, 0 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-06-17 15:27 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Borislav Petkov, Peter Zijlstra, Ingo Molnar,
	Frederic Weisbecker, Steven Rostedt, Lin Ming, linux-kernel

From: Arnaldo Carvalho de Melo <acme@infradead.org>
Date: Thu, Jun 17, 2010 at 11:25:46AM -0300

> Em Thu, Jun 17, 2010 at 03:43:57PM +0200, Borislav Petkov escreveu:
> > From: Arnaldo Carvalho de Melo <acme@infradead.org>
> > Date: Mon, Jun 14, 2010 at 10:02:01PM -0300
> > > > however, this does not differentiate perflib (let's call it that for how
> > > > :) from libc headers. Do we want a "perf" or "kernel" or "perflib" or
> > > > whatever prefix here - it might make sense later when this thing grows
> > > > to differentiate between the namespaces...?
> 
> > > Agreed, but the last name this thing will have will be 'perf'something :-)
> > > One of the goals at least I have with pursuing this path is to separate
> > > out everything that is not strictly 'perf' into things that can be reused
> > > by other tools, like yours.
> 
> > I'm still splitting perf/util into a more or less generic lib.  Now, I
> > want to reuse as much code as possible and am parsing the
> > "mce:mce_record" tracepoint using parse_events(). However, this means
> > that I have to push the not-so-generic perf bits like
> > util/parse-events.c into the lib. Which, in turn, pulls in
> > util/trace-event* etc.
> 
> I'm not that familiar with the trace bits in perf, but I'd say pick what
> is needed for your tool and stash it into files in a tools/lib/trace/
> directory, in a way that can be used by both perf and your tools.
> 
> I.e. no need to move files as-is, you can reorganize things to make it
> useful for both perf and your tool.

Right, this is the idea. However, all those header includes pull in
other stuff. For example, if I want to use parse_events(), it pulls in
parse-options.* which pulls in header.h, symbol.h etc.

What I ended up doing is have

tools/lib/perf/
	 /trace/
	 /include/
	 /lk/

for all the different types of facilities. So lk contains the generic
perf/util/ stuff, include contains all the linux and asm headers like
bitops.h, hash.h, kernel.h etc, perf contains parse-events.* because it
deals with perf stuff and so on.

How's that?

> > What is your preference, do we want to export all perf/util stuff for
> > other tools to use or rather link other tools together with
> > compilation modules from perf/util in case those other tools need
> > them?
> 
> If we do it on a as-needed basis, as I suggested, we go eroding the
> current perf hodgepodge of potentially generic stuff.

I think splitting it in kinda "subsystems" helps keep the modularity.

Opinions, comments?

-- 
Regards/Gruss,
Boris.

Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Gemeinde Aschheim, Landkreis München
Registergericht Muenchen, HRB Nr. 43632

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-17 13:43                                     ` Borislav Petkov
  2010-06-17 14:25                                       ` Arnaldo Carvalho de Melo
@ 2010-06-17 16:19                                       ` Steven Rostedt
  2010-06-17 17:31                                         ` Borislav Petkov
  1 sibling, 1 reply; 31+ messages in thread
From: Steven Rostedt @ 2010-06-17 16:19 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Arnaldo Carvalho de Melo, Borislav Petkov, Peter Zijlstra,
	Ingo Molnar, Frederic Weisbecker, Lin Ming, linux-kernel

On Thu, 2010-06-17 at 15:43 +0200, Borislav Petkov wrote:

> > One of the goals at least I have with pursuing this path is to separate
> > out everything that is not strictly 'perf' into things that can be reused
> > by other tools, like yours.
> 
> I'm still splitting perf/util into a more or less generic lib.
> Now, I want to reuse as much code as possible and am parsing
> the "mce:mce_record" tracepoint using parse_events(). However,
> this means that I have to push the not-so-generic perf bits
> like util/parse-events.c into the lib. Which, in turn, pulls in
> util/trace-event* etc.

Note, I have a separate generic library in trace-cmd that has the
parsing of trace events as its own library now.

This is the code that started trace-event-parse.c.

It has evolved quite a bit since then. You can get the code from:

  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git

The files are parse-events.c and parse-events.h. As well as some
filtering code: parse-filter.c.

It creates a libparsevent library.

I've been meaning to update the perf stuff with it, but just have not
had the time. Seems that what you are doing might be a good fit for it.

-- Steve



^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-06-17 16:19                                       ` Steven Rostedt
@ 2010-06-17 17:31                                         ` Borislav Petkov
  0 siblings, 0 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-06-17 17:31 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Arnaldo Carvalho de Melo, Borislav Petkov, Peter Zijlstra,
	Ingo Molnar, Frederic Weisbecker, Lin Ming, linux-kernel

From: Steven Rostedt <rostedt@goodmis.org>
Date: Thu, Jun 17, 2010 at 12:19:57PM -0400

> On Thu, 2010-06-17 at 15:43 +0200, Borislav Petkov wrote:
> 
> > > One of the goals at least I have with pursuing this path is to separate
> > > out everything that is not strictly 'perf' into things that can be reused
> > > by other tools, like yours.
> > 
> > I'm still splitting perf/util into a more or less generic lib.
> > Now, I want to reuse as much code as possible and am parsing
> > the "mce:mce_record" tracepoint using parse_events(). However,
> > this means that I have to push the not-so-generic perf bits
> > like util/parse-events.c into the lib. Which, in turn, pulls in
> > util/trace-event* etc.
> 
> Note, I have a separate generic library in trace-cmd that has the
> parsing of trace events as its own library now.
> 
> This is the code that started trace-event-parse.c.
> 
> It has evolved quite a bit since then. You can get the code from:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git
> 
> The files are parse-events.c and parse-events.h. As well as some
> filtering code: parse-filter.c.
> 
> It creates a libparsevent library.
> 
> I've been meaning to update the perf stuff with it, but just have not
> had the time. Seems that what you are doing might be a good fit for it.

I see, well, I could take it and merge it into tools/trace-cmd or
something and then we all could gradually weed out common code. But I'm
open to other suggestions as well.

I mean, it is only natural if we merry perf and ftrace in kernel space
to do the same in userspace, right :)

-- 
Regards/Gruss,
Boris.

Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Gemeinde Aschheim, Landkreis München
Registergericht Muenchen, HRB Nr. 43632

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-22 19:04 ` [PATCH 1/2] perf: Add persistent events Borislav Petkov
  2010-05-22 19:14   ` Borislav Petkov
@ 2010-05-25  3:11   ` Steven Rostedt
  1 sibling, 0 replies; 31+ messages in thread
From: Steven Rostedt @ 2010-05-25  3:11 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Frederic Weisbecker, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel,
	Borislav Petkov

On Sat, 2010-05-22 at 21:04 +0200, Borislav Petkov wrote:
> From: Borislav Petkov <bp@alien8.de>
> 
> Register and enable events marked as persistent right after perf events
> has initialized.
> 
> Not-yet-signed-off-by: Borislav Petkov <bp@alien8.de>
> ---
>  include/linux/ftrace_event.h |   10 +++++++
>  include/linux/perf_event.h   |    1 +
>  kernel/perf_event.c          |   59 +++++++++++++++++++++++++++++++++++++----
>  kernel/trace/trace.h         |    1 -
>  4 files changed, 64 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
> index c0f4b36..b40d637 100644
> --- a/include/linux/ftrace_event.h
> +++ b/include/linux/ftrace_event.h
> @@ -13,6 +13,8 @@ struct dentry;
>  
>  DECLARE_PER_CPU(struct trace_seq, ftrace_event_seq);
>  
> +extern struct list_head ftrace_events;
> +
>  struct trace_print_flags {
>  	unsigned long		mask;
>  	const char		*name;
> @@ -134,6 +136,7 @@ struct ftrace_event_call {
>  	int			perf_refcount;
>  	int			(*perf_event_enable)(struct ftrace_event_call *);
>  	void			(*perf_event_disable)(struct ftrace_event_call *);
> +	unsigned int		type;
>  };

If you look at lastest tip/perf/core, can you add this to the
ftrace_event_class instead. Or if it must be per event, can we find a
way to include it into the flags field. Changes to flags must have the
event_mutex held.

-- Steve

>  
>  #define PERF_MAX_TRACE_SIZE	2048
> @@ -155,6 +158,13 @@ enum {
>  	FILTER_PTR_STRING,
>  };




^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH 1/2] perf: Add persistent events
  2010-05-22 19:04 ` [PATCH 1/2] perf: Add persistent events Borislav Petkov
@ 2010-05-22 19:14   ` Borislav Petkov
  2010-05-25  3:11   ` Steven Rostedt
  1 sibling, 0 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-05-22 19:14 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Ingo Molnar, Frederic Weisbecker, Steven Rostedt, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Lin Ming, linux-kernel

From: Borislav Petkov <bp@amd64.org>
Date: Sat, May 22, 2010 at 09:04:47PM +0200

> Register and enable events marked as persistent right after perf events
> has initialized.
> 
> Not-yet-signed-off-by: Borislav Petkov <bp@alien8.de>
> ---
>  include/linux/ftrace_event.h |   10 +++++++
>  include/linux/perf_event.h   |    1 +
>  kernel/perf_event.c          |   59 +++++++++++++++++++++++++++++++++++++----
>  kernel/trace/trace.h         |    1 -
>  4 files changed, 64 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
> index c0f4b36..b40d637 100644
> --- a/include/linux/ftrace_event.h
> +++ b/include/linux/ftrace_event.h
> @@ -13,6 +13,8 @@ struct dentry;
>  
>  DECLARE_PER_CPU(struct trace_seq, ftrace_event_seq);
>  
> +extern struct list_head ftrace_events;
> +
>  struct trace_print_flags {
>  	unsigned long		mask;
>  	const char		*name;
> @@ -134,6 +136,7 @@ struct ftrace_event_call {
>  	int			perf_refcount;
>  	int			(*perf_event_enable)(struct ftrace_event_call *);
>  	void			(*perf_event_disable)(struct ftrace_event_call *);
> +	unsigned int		type;
>  };
>  
>  #define PERF_MAX_TRACE_SIZE	2048
> @@ -155,6 +158,13 @@ enum {
>  	FILTER_PTR_STRING,
>  };
>  
> +enum event_type_t {
> +	EVENT_FLEXIBLE = 0x1,
> +	EVENT_PINNED = 0x2,
> +	EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
> +	EVENT_PERSISTENT = 0x3,
> +};

Doh,

I meant

enum event_type_t {
	EVENT_FLEXIBLE = 0x1,
	EVENT_PINNED = 0x2,
	EVENT_PERSISTENT = 0x4,
	EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED | EVENT_PERSISTENT,
};

here.

> +
>  extern int trace_event_raw_init(struct ftrace_event_call *call);
>  extern int trace_define_field(struct ftrace_event_call *call, const char *type,
>  			      const char *name, int offset, int size,
> diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
> index c8e3754..aa62c97 100644
> --- a/include/linux/perf_event.h
> +++ b/include/linux/perf_event.h
> @@ -579,6 +579,7 @@ struct perf_event {
>  	struct list_head		group_entry;
>  	struct list_head		event_entry;
>  	struct list_head		sibling_list;
> +	struct list_head		pevent_entry;
>  	int				nr_siblings;
>  	int				group_flags;
>  	struct perf_event		*group_leader;
> diff --git a/kernel/perf_event.c b/kernel/perf_event.c
> index 3d1552d..84f2f36 100644
> --- a/kernel/perf_event.c
> +++ b/kernel/perf_event.c
> @@ -72,6 +72,11 @@ static atomic64_t perf_event_id;
>  static DEFINE_SPINLOCK(perf_resource_lock);
>  
>  /*
> + * persistent events which are always on
> + */
> +DEFINE_PER_CPU(struct list_head, persistent_events);
> +
> +/*
>   * Architecture provided APIs - weak aliases:
>   */
>  extern __weak const struct pmu *hw_perf_event_init(struct perf_event *event)
> @@ -1017,12 +1022,6 @@ static int perf_event_refresh(struct perf_event *event, int refresh)
>  	return 0;
>  }
>  
> -enum event_type_t {
> -	EVENT_FLEXIBLE = 0x1,
> -	EVENT_PINNED = 0x2,
> -	EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
> -};
> -
>  static void ctx_sched_out(struct perf_event_context *ctx,
>  			  struct perf_cpu_context *cpuctx,
>  			  enum event_type_t event_type)
> @@ -5385,6 +5384,8 @@ static void __init perf_event_init_all_cpus(void)
>  	for_each_possible_cpu(cpu) {
>  		cpuctx = &per_cpu(perf_cpu_context, cpu);
>  		__perf_event_init_context(&cpuctx->ctx, NULL);
> +
> +		INIT_LIST_HEAD(&per_cpu(persistent_events, cpu));
>  	}
>  }
>  
> @@ -5405,12 +5406,16 @@ static void __perf_event_exit_cpu(void *info)
>  	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
>  	struct perf_event_context *ctx = &cpuctx->ctx;
>  	struct perf_event *event, *tmp;
> +	struct list_head *pers_events_list = &__get_cpu_var(persistent_events);
>  
>  	list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
>  		__perf_event_remove_from_context(event);
>  	list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
>  		__perf_event_remove_from_context(event);
> +	list_for_each_entry_safe(event, tmp, pers_events_list, pevent_entry)
> +		__perf_event_remove_from_context(event);
>  }
> +
>  static void perf_event_exit_cpu(int cpu)
>  {
>  	struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
> @@ -5456,6 +5461,46 @@ static struct notifier_block __cpuinitdata perf_cpu_nb = {
>  	.priority		= 20,
>  };
>  
> +static void __init perf_init_persistent_events(void)
> +{
> +
> +	struct ftrace_event_call *call;
> +	struct perf_event_attr attr;
> +	struct perf_event *event;
> +	int cpu;
> +
> +	list_for_each_entry(call, &ftrace_events, list) {
> +
> +		if (call->type != EVENT_PERSISTENT)
> +			continue;
> +
> +		attr.type	= PERF_TYPE_TRACEPOINT,
> +		attr.config	= call->id,
> +		attr.size	= sizeof(attr),
> +
> +		get_online_cpus();
> +
> +		for_each_online_cpu(cpu) {
> +			struct list_head *list;
> +
> +			event = perf_event_create_kernel_counter(&attr, cpu, -1, NULL);
> +			if (IS_ERR(event)) {
> +				printk(KERN_ERR "Error initializing persistent "
> +						"event %s on cpu %d\n",
> +						call->name, cpu);
> +				break;
> +			}
> +
> +			list = &per_cpu(persistent_events, cpu);
> +			list_add(&event->pevent_entry, list);
> +
> +			perf_event_enable(event);
> +
> +		}
> +		put_online_cpus();
> +	}
> +}
> +
>  void __init perf_event_init(void)
>  {
>  	perf_event_init_all_cpus();
> @@ -5464,6 +5509,8 @@ void __init perf_event_init(void)
>  	perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
>  			(void *)(long)smp_processor_id());
>  	register_cpu_notifier(&perf_cpu_nb);
> +
> +	perf_init_persistent_events();
>  }
>  
>  static ssize_t perf_show_reserve_percpu(struct sysdev_class *class,
> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index 2825ef2..95f5611 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -786,7 +786,6 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
>  }
>  
>  extern struct mutex event_mutex;
> -extern struct list_head ftrace_events;
>  
>  extern const char *__start___trace_bprintk_fmt[];
>  extern const char *__stop___trace_bprintk_fmt[];
> -- 
> 1.7.1
> 
> 

-- 
Regards/Gruss,
    Boris.

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH 1/2] perf: Add persistent events
  2010-05-22 19:04 Borislav Petkov
@ 2010-05-22 19:04 ` Borislav Petkov
  2010-05-22 19:14   ` Borislav Petkov
  2010-05-25  3:11   ` Steven Rostedt
  0 siblings, 2 replies; 31+ messages in thread
From: Borislav Petkov @ 2010-05-22 19:04 UTC (permalink / raw)
  To: Ingo Molnar, Frederic Weisbecker, Steven Rostedt, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Lin Ming
  Cc: linux-kernel, Borislav Petkov

From: Borislav Petkov <bp@alien8.de>

Register and enable events marked as persistent right after perf events
has initialized.

Not-yet-signed-off-by: Borislav Petkov <bp@alien8.de>
---
 include/linux/ftrace_event.h |   10 +++++++
 include/linux/perf_event.h   |    1 +
 kernel/perf_event.c          |   59 +++++++++++++++++++++++++++++++++++++----
 kernel/trace/trace.h         |    1 -
 4 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index c0f4b36..b40d637 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -13,6 +13,8 @@ struct dentry;
 
 DECLARE_PER_CPU(struct trace_seq, ftrace_event_seq);
 
+extern struct list_head ftrace_events;
+
 struct trace_print_flags {
 	unsigned long		mask;
 	const char		*name;
@@ -134,6 +136,7 @@ struct ftrace_event_call {
 	int			perf_refcount;
 	int			(*perf_event_enable)(struct ftrace_event_call *);
 	void			(*perf_event_disable)(struct ftrace_event_call *);
+	unsigned int		type;
 };
 
 #define PERF_MAX_TRACE_SIZE	2048
@@ -155,6 +158,13 @@ enum {
 	FILTER_PTR_STRING,
 };
 
+enum event_type_t {
+	EVENT_FLEXIBLE = 0x1,
+	EVENT_PINNED = 0x2,
+	EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
+	EVENT_PERSISTENT = 0x3,
+};
+
 extern int trace_event_raw_init(struct ftrace_event_call *call);
 extern int trace_define_field(struct ftrace_event_call *call, const char *type,
 			      const char *name, int offset, int size,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index c8e3754..aa62c97 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -579,6 +579,7 @@ struct perf_event {
 	struct list_head		group_entry;
 	struct list_head		event_entry;
 	struct list_head		sibling_list;
+	struct list_head		pevent_entry;
 	int				nr_siblings;
 	int				group_flags;
 	struct perf_event		*group_leader;
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 3d1552d..84f2f36 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -72,6 +72,11 @@ static atomic64_t perf_event_id;
 static DEFINE_SPINLOCK(perf_resource_lock);
 
 /*
+ * persistent events which are always on
+ */
+DEFINE_PER_CPU(struct list_head, persistent_events);
+
+/*
  * Architecture provided APIs - weak aliases:
  */
 extern __weak const struct pmu *hw_perf_event_init(struct perf_event *event)
@@ -1017,12 +1022,6 @@ static int perf_event_refresh(struct perf_event *event, int refresh)
 	return 0;
 }
 
-enum event_type_t {
-	EVENT_FLEXIBLE = 0x1,
-	EVENT_PINNED = 0x2,
-	EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
-};
-
 static void ctx_sched_out(struct perf_event_context *ctx,
 			  struct perf_cpu_context *cpuctx,
 			  enum event_type_t event_type)
@@ -5385,6 +5384,8 @@ static void __init perf_event_init_all_cpus(void)
 	for_each_possible_cpu(cpu) {
 		cpuctx = &per_cpu(perf_cpu_context, cpu);
 		__perf_event_init_context(&cpuctx->ctx, NULL);
+
+		INIT_LIST_HEAD(&per_cpu(persistent_events, cpu));
 	}
 }
 
@@ -5405,12 +5406,16 @@ static void __perf_event_exit_cpu(void *info)
 	struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context);
 	struct perf_event_context *ctx = &cpuctx->ctx;
 	struct perf_event *event, *tmp;
+	struct list_head *pers_events_list = &__get_cpu_var(persistent_events);
 
 	list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
 		__perf_event_remove_from_context(event);
 	list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
 		__perf_event_remove_from_context(event);
+	list_for_each_entry_safe(event, tmp, pers_events_list, pevent_entry)
+		__perf_event_remove_from_context(event);
 }
+
 static void perf_event_exit_cpu(int cpu)
 {
 	struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu);
@@ -5456,6 +5461,46 @@ static struct notifier_block __cpuinitdata perf_cpu_nb = {
 	.priority		= 20,
 };
 
+static void __init perf_init_persistent_events(void)
+{
+
+	struct ftrace_event_call *call;
+	struct perf_event_attr attr;
+	struct perf_event *event;
+	int cpu;
+
+	list_for_each_entry(call, &ftrace_events, list) {
+
+		if (call->type != EVENT_PERSISTENT)
+			continue;
+
+		attr.type	= PERF_TYPE_TRACEPOINT,
+		attr.config	= call->id,
+		attr.size	= sizeof(attr),
+
+		get_online_cpus();
+
+		for_each_online_cpu(cpu) {
+			struct list_head *list;
+
+			event = perf_event_create_kernel_counter(&attr, cpu, -1, NULL);
+			if (IS_ERR(event)) {
+				printk(KERN_ERR "Error initializing persistent "
+						"event %s on cpu %d\n",
+						call->name, cpu);
+				break;
+			}
+
+			list = &per_cpu(persistent_events, cpu);
+			list_add(&event->pevent_entry, list);
+
+			perf_event_enable(event);
+
+		}
+		put_online_cpus();
+	}
+}
+
 void __init perf_event_init(void)
 {
 	perf_event_init_all_cpus();
@@ -5464,6 +5509,8 @@ void __init perf_event_init(void)
 	perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
 			(void *)(long)smp_processor_id());
 	register_cpu_notifier(&perf_cpu_nb);
+
+	perf_init_persistent_events();
 }
 
 static ssize_t perf_show_reserve_percpu(struct sysdev_class *class,
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 2825ef2..95f5611 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -786,7 +786,6 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
 }
 
 extern struct mutex event_mutex;
-extern struct list_head ftrace_events;
 
 extern const char *__start___trace_bprintk_fmt[];
 extern const char *__stop___trace_bprintk_fmt[];
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2010-06-17 17:31 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-22 19:00 [RFC PATCH 0/2] perf: persistent events prototype Borislav Petkov
2010-05-22 19:00 ` [PATCH 2/2] x86, mce: Make MCE tracepoint persistent event Borislav Petkov
     [not found] ` <1274554806-28216-2-git-send-email-bp@alien8.de>
2010-05-23 18:15   ` [PATCH 1/2] perf: Add persistent events Peter Zijlstra
2010-05-23 18:33     ` Borislav Petkov
2010-05-23 18:40       ` Peter Zijlstra
2010-05-23 18:54         ` Borislav Petkov
2010-05-23 19:23           ` Peter Zijlstra
2010-05-25  7:32             ` Borislav Petkov
2010-05-25 14:59               ` Peter Zijlstra
2010-05-28 14:33                 ` Ingo Molnar
2010-05-28 15:17                   ` Peter Zijlstra
2010-05-28 15:57                     ` Borislav Petkov
2010-05-28 18:07                       ` Peter Zijlstra
2010-06-03 13:43                         ` Borislav Petkov
2010-06-03 17:32                           ` Arnaldo Carvalho de Melo
2010-06-03 21:39                             ` Borislav Petkov
2010-06-14 19:25                             ` Borislav Petkov
2010-06-14 21:01                               ` Arnaldo Carvalho de Melo
2010-06-14 21:24                                 ` Borislav Petkov
2010-06-15  1:02                                   ` Arnaldo Carvalho de Melo
2010-06-15 10:22                                     ` Borislav Petkov
2010-06-15 13:22                                       ` Arnaldo Carvalho de Melo
2010-06-17 13:43                                     ` Borislav Petkov
2010-06-17 14:25                                       ` Arnaldo Carvalho de Melo
2010-06-17 15:27                                         ` Borislav Petkov
2010-06-17 16:19                                       ` Steven Rostedt
2010-06-17 17:31                                         ` Borislav Petkov
2010-05-23 20:36 ` [RFC PATCH 0/2] perf: persistent events prototype Steven Rostedt
2010-05-22 19:04 Borislav Petkov
2010-05-22 19:04 ` [PATCH 1/2] perf: Add persistent events Borislav Petkov
2010-05-22 19:14   ` Borislav Petkov
2010-05-25  3:11   ` Steven Rostedt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.