markers: example of irq regular kernel markers
Subsystems (4)
RFC PATCH 2/2 markers: example of irq regular kernel markers
Add trace points of irq handle events ported from LTTng's markers.
---
I just rewrote LTTng's irq event by using DEFINE_TRACE for example.
include/linux/irq_trace.h | 6 ++++++ kernel/irq/handle.c | 6 ++++++ 2 files changed, 12 insertions(+)
include/linux/irq_trace.h new file +6 -0
@@ -0,0 +1,6 @@ +#include <linux/marker.h> + +DEFINE_TRACE(irq_entry, (int irq_id, int kernel_mode), irq_id, kernel_mode); + +DEFINE_TRACE(irq_exit, (void)); +
kernel/irq/handle.c +6 -0
@@ -15,6 +15,7 @@#include <linux/random.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> +#include <linux/irq_trace.h> #include "internals.h"
@@ -130,6 +131,9 @@ irqreturn_t handle_IRQ_event(unsigned in {irqreturn_t ret, retval =IRQ_NONE ;unsigned int status =0 ; +struct pt_regs *regs =get_irq_regs (); + +trace_irq_entry (irq, (regs)?(!user_mode (regs)):(1 ));handle_dynamic_tick (action);
@@ -148,6 +152,8 @@ irqreturn_t handle_IRQ_event(unsigned inadd_interrupt_randomness (irq);local_irq_disable (); +trace_irq_exit (); +return retval; }
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Quoted 15 lines · * Masami Hiramatsu ([email protected]) wrote:
Add trace points of irq handle events ported from LTTng's markers.
Signed-off-by Masami Hiramatsu <[email protected]>---
I just rewrote LTTng's irq event by usingDEFINE_TRACEfor example.include/linux/irq_trace.h | 6 ++++++ kernel/irq/handle.c | 6 ++++++ 2 files changed, 12 insertions(+)Index:
2.6.26-rc5-mm3/include/linux/irq_trace.h
===================================================================
include/linux/irq_trace.h line 6
Quoted 6 lines
include/linux/irq_trace.h new file +6
-0@@ -0,0 +1,6 @@ +#include <linux/marker.h> + +DEFINE_TRACE(irq_entry, (int irq_id, int kernel_mode), irq_id, kernel_mode); + +DEFINE_TRACE(irq_exit, (void)); +
All this work look good, thanks Masami! Sorry I did not find time to do it lately, I've been busy on other things. A small question though :
since LTTng is configurable both as an external module or as an in-kernel tracer, I wonder if it would really hurt to add the format strings to DEFINE_TRACE, e.g. :
DEFINE_TRACE(name, prototype, format_string, args...)
which would give :
DEFINE_TRACE(irq_entry, (int irq_id, int kernel_mode), "%d %d",
irq_id, kernel_mode);
DEFINE_TRACE(irq_exit, (void), MARK_NOARGS);
and calling this in the kernel code :
trace_irq_entry(irq, (regs)?(!user_mode(regs)):(1));
...trace_irq_exit();
and for quick-and-dirty debug usage, one would add this to kernel code :
trace_mark(subsystem_event, "(int arg, struct task_struct *task)",
"%d %p", arg, current);
By doing so, we could leave a gcc format string check by passing the format string to __mark_check_format(). We could extract the field names from the prototype, so there is no need to duplicate field information in the format string.
Since the format string information is hidden in a header but kept at the same location as the trace point definition, I think it reaches goals of being "neat", efficient for general purpose tracers and to keep the tracepoint information all in one place so we don't end up adding stuff to various information consumers whenever a new trace point is added.
What do you think of these changes ?
Mathieu
Quoted 40 lines
Index:
2.6.26-rc5-mm3/kernel/irq/handle.c
===================================================================kernel/irq/handle.c +6
-0@@ -15,6 +15,7 @@#include <linux/random.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> +#include <linux/irq_trace.h> #include "internals.h" @@ -130,6 +131,9 @@ irqreturn_t handle_IRQ_event(unsigned in {irqreturn_t ret, retval =IRQ_NONE ;unsigned int status =0 ; +struct pt_regs *regs =get_irq_regs (); + +trace_irq_entry (irq, (regs)?(!user_mode (regs)):(1 ));handle_dynamic_tick (action);@@ -148,6 +152,8 @@ irqreturn_t handle_IRQ_event(unsigned inadd_interrupt_randomness (irq);local_irq_disable (); +trace_irq_exit (); +return retval; }Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Hi Mathieu,
Quoted 40 lines · Mathieu Desnoyers
Quoted 15 lines · * Masami Hiramatsu ([email protected]) wrote:
Add trace points of irq handle events ported from LTTng's markers.
Signed-off-by Masami Hiramatsu <[email protected]>---
I just rewrote LTTng's irq event by usingDEFINE_TRACEfor example.include/linux/irq_trace.h | 6 ++++++ kernel/irq/handle.c | 6 ++++++ 2 files changed, 12 insertions(+)Index:
2.6.26-rc5-mm3/include/linux/irq_trace.h
===================================================================include/linux/irq_trace.h line 6
Quoted 6 lines
include/linux/irq_trace.h new file +6
-0@@ -0,0 +1,6 @@ +#include <linux/marker.h> + +DEFINE_TRACE(irq_entry, (int irq_id, int kernel_mode), irq_id, kernel_mode); + +DEFINE_TRACE(irq_exit, (void)); +All this work look good, thanks Masami! Sorry I did not find time to do it lately, I've been busy on other things. A small question though :
since LTTng is configurable both as an external module or as an in-kernel tracer, I wonder if it would really hurt to add the format strings toDEFINE_TRACE, e.g. :
DEFINE_TRACE(name, prototype, format_string, args...)which would give :
DEFINE_TRACE(irq_entry, (int
irq_id, intkernel_mode), "%d %d",irq_id, kernel_mode);
DEFINE_TRACE(irq_exit, (void), MARK_NOARGS);and calling this in the kernel code :
Quoted 8 lines
trace_irq_entry(irq, (regs)?(!user_mode(regs)):(1));
...trace_irq_exit();and for quick-and-dirty debug usage, one would add this to kernel code :
trace_mark(subsystem_event, "(int arg, struct
task_struct*task)",
"%d %p", arg, current);
why would you complicate it? I think.
trace_mark(subsystem_event, "arg %d task %p", arg, current);
is enough for user-defined markers.
Quoted 5 lines
By doing so, we could leave a gcc format string check by passing the format string to
__mark_check_format(). We could extract the field names from the prototype, so there is no need to duplicate field information in the format string.
I thought that someone complained against those format strings in kernel code. Thus I removed it from DEFINE_TRACE.
even though, I think you can do that by adding below string table to LTTng module.
const char *lookup_table[MAX_MARKERS][2] = {
{"irq_entry", "%d %d"}, // or "(int irq_id, int kernel_mode)", "%d %d"
...
};
Quoted 7 lines
Since the format string information is hidden in a header but kept at the same location as the trace point definition, I think it reaches goals of being "neat", efficient for general purpose tracers and to keep the tracepoint information all in one place so we don't end up adding stuff to various information consumers whenever a new trace point is added.
Hmm, IMHO, there seems no difference between
DEFINE_TRACE(irq_entry, (int irq_id, int kernel_mode), "%d %d",
irq_id, kernel_mode);
and
trace_irq_entry(int irq_id, int kernel_mode)
{
trace_mark(irq_entry, "%d %d", irq_id, kernel_mode);
}for me. If so, we'd better use latter because of simplicity:-)
Thank you,
Quoted 47 lines
What do you think of these changes ?
Mathieu
Quoted 40 lines
Index:
2.6.26-rc5-mm3/kernel/irq/handle.c
===================================================================kernel/irq/handle.c +6
-0@@ -15,6 +15,7 @@#include <linux/random.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> +#include <linux/irq_trace.h> #include "internals.h" @@ -130,6 +131,9 @@ irqreturn_t handle_IRQ_event(unsigned in {irqreturn_t ret, retval =IRQ_NONE ;unsigned int status =0 ; +struct pt_regs *regs =get_irq_regs (); + +trace_irq_entry (irq, (regs)?(!user_mode (regs)):(1 ));handle_dynamic_tick (action);@@ -148,6 +152,8 @@ irqreturn_t handle_IRQ_event(unsigned inadd_interrupt_randomness (irq);local_irq_disable (); +trace_irq_exit (); +return retval; }Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Hi!
Quoted 8 lines
Quoted 4 lines
By doing so, we could leave a gcc format string check by passing the format string to
__mark_check_format(). We could extract the field names from the prototype, so there is no need to duplicate field information in the format string.I thought that someone complained against those format strings in kernel code. Thus I removed it from
DEFINE_TRACE.
Quoted 7 lines
even though, I think you can do that by adding below string table to LTTng module.
const char *lookup_table[MAX_MARKERS][2] = {
{"irq_entry", "%d %d"}, // or "(intirq_id, intkernel_mode)", "%d %d"
...
};
if move string to out of kernel core, compiler may kill some variable. thus, we will get incomplete tracing result.
I think your proposal is very interesting.
but I dont understand why someone dislike format strings. Could you explain this reason?
Steven Rostedt
maintainerQuoted 11 lines · KOSAKI Motohiro
Quoted 8 lines
even though, I think you can do that by adding below string table to LTTng module.
const char *lookup_table[MAX_MARKERS][2] = {
{"irq_entry", "%d %d"}, // or "(intirq_id, intkernel_mode)", "%d %d"
...
};if move string to out of kernel core, compiler may kill some variable. thus, we will get incomplete tracing result.
I don't understand why the compiler would do such a thing? The compiler shouldn't be removing parameters.
Quoted 4 lines
I think your proposal is very interesting.
but I dont understand why someone dislike format strings. Could you explain this reason?
Format strings only help for printf like operations. Not all tracers want such a thing. The best example of this is the sched_switch code. LTTng and friends just want a pid and comm to show. But there's tracers that want more info from the task_struct. We also like to see the priority of the task.
I also foresee these trace hooks be use for dynamic itegrity checks. On switching out a process we might want to examine both the next and prev to make sure the context switch should really occur.
There's other places in the core kernel that a tracer wants more than some data in a structure. Recording all the data that might be needed in a structure slows down those tracers that only want a little bit of data. Passing in a pointer to the structure being traced should be enough for all tracers.
If those that don't care about priority of a context switch, why should it be parsing it out just for a single tracer that might need it. But all tracers would need the prev and next pointers.
Now back to your question, why don't we like the printf format. Simply because it does nothing for pointers. It might help you with a %d and number of parameters, but a %p can not tell the difference between a struct tasks_struct *, and a int *, which can have even more devastating results. It also just looks like a debug session instead of a trace marker.
Not to mention what Peter Zijlstra already stated, that a printf format gives only run time checking, where we would like to see compile time checking.
-- Steve
Quoted 1 line · Steven Rostedt
[...] Format strings only help for printf like operations. [...]
That is not so. They are far from panaceanic, but printf formats are useful for type checked simple scalars, which we can extract and use for purposes other than printf like operations.
Quoted 4 lines
The best example of this is the
sched_switchcode. LTTng and friends just want a pid and comm to show. But there's tracers that want more info from thetask_struct. We also like to see the priority of the task. [...]
This is the sort of information that can help generate a compromise. For this case, pass a few raw pointers that a compiled-in tracing engine can dereference at will, and *also pass* a few user-level scalars that a separately-compiled tracing engine can use.
Quoted 2 lines
Passing in a pointer to the structure being traced should be enough for all tracers.
On the contrary, we have explained why *this is not so*. Using raw general structure pointers in impractical for some tracers.
Quoted 5 lines
Now back to your question, why don't we like the printf format. Simply because it does nothing for pointers. It might help you with a %d and number of parameters, but a %p can not tell the difference between a struct
tasks_struct*, and a int *, which can have even more devastating results.
Indeed. Unfortunately, C is not kind to us in the way that perhaps C++ templates could be. We have not yet seen a single mechanism that does all of:
- type-safe passing of arbitrary pointer/etc. types (so compiled-in trace data consumers can go wild with data passing)
- declarative / separately-compiled consumption of types (so lttng/systemtap/userspace can hook in without heroics)
- parsimonious implementation
Maybe a solution could involve some restrictions on the generalities. For example, can we narrow down the number of different scalar + pointer types to a fixed handful? Can we tolerate type-safety being provided by families of function declarations rather than one generic one?
Quoted 1 line
It also just looks like a debug session instead of a trace marker.
Why do you think the difference between those is profound?
- FChE
Steven Rostedt
maintainerQuoted 7 lines · Frank Ch. Eigler
Quoted 1 line · Steven Rostedt
[...] Format strings only help for printf like operations. [...]
That is not so. They are far from panaceanic, but printf formats are useful for type checked simple scalars, which we can extract and use for purposes other than printf like operations.
It doesn't help much if you mix a pid and prio of a task_struct, and then use the prio to find the actual task, or try setting another task priority to the pid.
Quoted 10 lines
Quoted 5 lines
The best example of this is the
sched_switchcode. LTTng and friends just want a pid and comm to show. But there's tracers that want more info from thetask_struct. We also like to see the priority of the task. [...]This is the sort of information that can help generate a compromise. For this case, pass a few raw pointers that a compiled-in tracing engine can dereference at will, and *also pass* a few user-level scalars that a separately-compiled tracing engine can use.
I definitely want the raw pointers for my tracers, but I understand why other tracers don't want them. And yes I would like a compromise here. I'm hoping for something where I don't need to skip over the scalers to get to the needed pointers. Things that Masami is suggesting is looking promising.
Quoted 6 lines
Quoted 3 lines
Passing in a pointer to the structure being traced should be enough for all tracers.
On the contrary, we have explained why *this is not so*. Using raw general structure pointers in impractical for some tracers.
The thing that those tracers need is something that can be stored in the kernel that can easily extract the needed information.
Quoted 17 lines
Quoted 6 lines
Now back to your question, why don't we like the printf format. Simply because it does nothing for pointers. It might help you with a %d and number of parameters, but a %p can not tell the difference between a struct
tasks_struct*, and a int *, which can have even more devastating results.Indeed. Unfortunately, C is not kind to us in the way that perhaps C++ templates could be. We have not yet seen a single mechanism that does all of:
- type-safe passing of arbitrary pointer/etc. types (so compiled-in trace data consumers can go wild with data passing)
- declarative / separately-compiled consumption of types (so lttng/systemtap/userspace can hook in without heroics)
- parsimonious implementation
Quoted 5 lines
Maybe a solution could involve some restrictions on the generalities. For example, can we narrow down the number of different scalar + pointer types to a fixed handful? Can we tolerate type-safety being provided by families of function declarations rather than one generic one?
I'm all for restricting this, I even suggested something similar a while ago (http://lists.openwall.net/linux-kernel/2006/10/07/21). No, I'm not pushing that solution, that solution was only to bring out more ideas.
Quoted 5 lines
Quoted 3 lines
It also just looks like a debug session instead of a trace marker.
Why do you think the difference between those is profound?
Not that profound but I do find:
trace_sched_switch(prev, next);
much nicer to look at than
trace_mark("%p %p", prev, next);The trace_sched_switch seems a bit more informative with a simple glance than the trace_mark.
-- Steve
Quoted 11 lines · Steven Rostedt
Quoted 5 lines · Frank Ch. Eigler
Quoted 1 line · Steven Rostedt
It also just looks like a debug session instead of a trace marker.
Why do you think the difference between those is profound?
Not that profound but I do find:
trace_sched_switch(prev, next);
Quoted 7 lines
much nicer to look at than
trace_mark("%p %p", prev, next);The
trace_sched_switchseems a bit more informative with a simple glance than thetrace_mark.
I think what Frank refers to here is why not scatter the kernel code with trace_mark()s on every conceivable location like you do with printk-style debugging. Those trace marks might help out when $customer's kernel goes splat and you don't want to provide him with a custom kernel.
I do think we must make a clear distinction between these cases because:
1) tracers provide a kernel<->user interface - and whilst we don't have
a stable in-kernel API/ABI we are anal about the kernel/user boundary. Andrew also greatly worries about this aspect.
2) it highly uglyfies the code, Frank doesn't need to maintain it, so
its easy for him to say. But IMHO its much harder to read code that is littered with debug statements that it is to read regular code.
3) it bloats the kernel,.. while it may not be fast path bloat, all
that marker stuff does go somewhere.
So, while I see the value of 'stable' mark sites for 'stable' events, I'm dead-set against littering the kernel with markers just because we can, and hoping they might some day be useful for someone.
Hi -
Quoted 3 lines · Peter Zijlstra
[...] I think what Frank refers to here is why not scatter the kernel code with trace_mark()s on every conceivable location like you do with printk-style debugging.
It's not fair to caricaturize my suggestions this way ("every conceivable location").
Quoted 2 lines
Those trace marks might help out when $customer's kernel goes splat and you don't want to provide him with a custom kernel.
Right.
Quoted 5 lines
I do think we must make a clear distinction between these cases because:
1) tracers provide a kernel<->user interface - and whilst we don't have a stable in-kernel API/ABI we are anal about the kernel/user boundary. Andrew also greatly worries about this aspect.
Well, how to set Andrew's mind at ease then, beyond what we've already said? Back a few months ago, both systemtap and lttng guys - the primary user-space clients - have said that we are fine with this interface changing. We each have mechanisms to adapt.
Quoted 4 lines
2) it highly uglyfies the code, Frank doesn't need to maintain it, so its easy for him to say. But IMHO its much harder to read code that is littered with debug statements that it is to read regular code.
Then don't put too many in, or hide them with inline functions.
Quoted 2 lines
3) it bloats the kernel,.. while it may not be fast path bloat, all
that marker stuff does go somewhere.
That bloat has been quantified and appears negligible in space and time.
Quoted 4 lines
So, while I see the value of 'stable' mark sites for 'stable' events, I'm dead-set against littering the kernel with markers just because we can, and hoping they might some day be useful for someone.
We're in violent agreement. No one suggested "littering just because we can". The initial lttng suite of markers consisted of about one hundred *in total*. If some other subsystem maintainer runs amok and adds thousands, please take it up with them, not with us.
- FChE
Hi,
Quoted 28 lines · Frank Ch. Eigler
Quoted 5 lines
I do think we must make a clear distinction between these cases because:
1) tracers provide a kernel<->user interface - and whilst we don't have a stable in-kernel API/ABI we are anal about the kernel/user boundary. Andrew also greatly worries about this aspect.
Well, how to set Andrew's mind at ease then, beyond what we've already said? Back a few months ago, both systemtap and lttng guys - the primary user-space clients - have said that we are fine with this interface changing. We each have mechanisms to adapt.
Quoted 4 lines
2) it highly uglyfies the code, Frank doesn't need to maintain it, so its easy for him to say. But IMHO its much harder to read code that is littered with debug statements that it is to read regular code.
Then don't put too many in, or hide them with inline functions.
Quoted 2 lines
3) it bloats the kernel,.. while it may not be fast path bloat, all
that marker stuff does go somewhere.That bloat has been quantified and appears negligible in space and time.
Quoted 4 lines
So, while I see the value of 'stable' mark sites for 'stable' events, I'm dead-set against littering the kernel with markers just because we can, and hoping they might some day be useful for someone.
Quoted 4 lines
We're in violent agreement. No one suggested "littering just because we can". The initial lttng suite of markers consisted of about one hundred *in total*. If some other subsystem maintainer runs amok and adds thousands, please take it up with them, not with us.
Indeed.
Peter, I thought, we were discussing what interface we could accept, not how many or where tracepoints we could accept. Or, am I misreading?
I know that if someone pushes markers into kernel in his own sweet way, of course, the kernel code will be bloated endlessly. But I also know why we review patches and send Ack/Nack before merging them to the tree. (If you still worry about it, we might be able to make linux-markers git tree, and review all regular markers on it)
I think and agree that we should make clear policies and criteria of acceptance of each marker, but it should be discussed on actual marker uses patches after making agreement for the interface.
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Quoted 8 lines
Peter, I thought, we were discussing what interface we could accept, not how many or where tracepoints we could accept. Or, am I misreading?
I know that if someone pushes markers into kernel in his own sweet way, of course, the kernel code will be bloated endlessly. But I also know why we review patches and send Ack/Nack before merging them to the tree. (If you still worry about it, we might be able to make linux-markers git tree, and review all regular markers on it)
Indeed.
if necessary, I can maintain this tree.
(because, I hope marker is independent by LTTng and SystemTap.
So, I am no related any tracer in this discussion member.)
but, at first,
We should review and discuss to Mathieu's new tracepoint proposal. I think that is good idea.
Quoted 8 lines · Steven Rostedt
[...]
Quoted 3 lines
That is not so. They are far from panaceanic, but printf formats are useful for type checked simple scalars, which we can extract and use for purposes other than printf like operations.
It doesn't help much if you mix a pid and prio of a
task_struct, and then use the prio to find the actual task, or try setting another task priority to the pid.
Right, though the same is true for a tracer client flipping around "next" and "prev" pointer values.
Quoted 9 lines
[...]
Quoted 5 lines
Quoted 2 lines
Passing in a pointer to the structure being traced should be enough for all tracers.
On the contrary, we have explained why *this is not so*. Using raw general structure pointers in impractical for some tracers.
The thing that those tracers need is something that can be stored in the kernel that can easily extract the needed information.
Well sure, but who is to do that storage & extraction? Some code the marker site maintainer needs to write for each marker?
Quoted 10 lines
[...]
Quoted 5 lines
Maybe a solution could involve some restrictions on the generalities. For example, can we narrow down the number of different scalar + pointer types to a fixed handful? Can we tolerate type-safety being provided by families of function declarations rather than one generic one?
I'm all for restricting this, I even suggested something similar a while ago (http://lists.openwall.net/linux-kernel/2006/10/07/21). No, I'm not pushing that solution, that solution was only to bring out more ideas.
Parts of that approach have a lot of merit. Perhaps we should spend some time cataloguing the types of all the lttng/logdev/blktrace "markers" and their nearby pointers. Maybe it's only a few dozen types altogether.
- FChE
Hi Motohiro,
Quoted 10 lines · KOSAKI Motohiro
Quoted 10 lines
Quoted 4 lines
By doing so, we could leave a gcc format string check by passing the format string to
__mark_check_format(). We could extract the field names from the prototype, so there is no need to duplicate field information in the format string.I thought that someone complained against those format strings in kernel code. Thus I removed it from
DEFINE_TRACE.even though, I think you can do that by adding below string table to LTTng module.
Quoted 7 lines
Quoted 4 lines
const char *lookup_table[MAX_MARKERS][2] = {
{"irq_entry", "%d %d"}, // or "(intirq_id, intkernel_mode)", "%d %d"
...
};if move string to out of kernel core, compiler may kill some variable. thus, we will get incomplete tracing result.
I think you might worry about the lookup_table variable will be removed by compiler if the variable is not referred from nowhere, right?
Here what I said is, if LTTng needs printf-style format, LTTng can "have" a lookup table in its module. In that case, since LTTng must have (at least one) functions which refers the lookup table, it is not optimized out.
Of course, LTTng maintainers have to put their eyes on changes of markers and related variables/structures, and change the lookup table if they need. (If they have a good c-style parameter parser, the maintenance cost can be reduced...)
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Quoted 17 lines · Mathieu Desnoyers
All this work look good, thanks Masami! Sorry I did not find time to do it lately, I've been busy on other things. A small question though :
since LTTng is configurable both as an external module or as an in-kernel tracer, I wonder if it would really hurt to add the format strings toDEFINE_TRACE, e.g. :
DEFINE_TRACE(name, prototype, format_string, args...)which would give :
DEFINE_TRACE(irq_entry, (int
irq_id, intkernel_mode), "%d %d",irq_id, kernel_mode);
DEFINE_TRACE(irq_exit, (void), MARK_NOARGS);and calling this in the kernel code :
Quoted 8 lines
trace_irq_entry(irq, (regs)?(!user_mode(regs)):(1));
...trace_irq_exit();and for quick-and-dirty debug usage, one would add this to kernel code :
trace_mark(subsystem_event, "(int arg, struct
task_struct*task)",
"%d %p", arg, current);
How would this work for:
DEFINE_TRACE(sched_switch, (struct task_struct *prev, struct task_struct *next), prev, next);
You'd want a string like: "%d %d", prev->pid, next->pid
not: "%p %p", prev, next
perhaps we can do something like:
DEFINE_TRACER(sched_switch, (struct task_struct *prev, struct task_struct *next), prev, next,
"%d %d", prev->pid, next->pid);
that defines a default tracer function for the previously defined trace point. That way its optional, and allows for generic trace points.
Of course, all this could be ruined by reality - C really sucks wrt forwarding functions.. :-/
[RFC] Tracepoint proposal
Quoted 37 lines · * Peter Zijlstra ([email protected]) wrote:
Quoted 17 lines · Mathieu Desnoyers
All this work look good, thanks Masami! Sorry I did not find time to do it lately, I've been busy on other things. A small question though :
since LTTng is configurable both as an external module or as an in-kernel tracer, I wonder if it would really hurt to add the format strings toDEFINE_TRACE, e.g. :
DEFINE_TRACE(name, prototype, format_string, args...)which would give :
DEFINE_TRACE(irq_entry, (int
irq_id, intkernel_mode), "%d %d",irq_id, kernel_mode);
DEFINE_TRACE(irq_exit, (void), MARK_NOARGS);and calling this in the kernel code :
Quoted 8 lines
trace_irq_entry(irq, (regs)?(!user_mode(regs)):(1));
...trace_irq_exit();and for quick-and-dirty debug usage, one would add this to kernel code :
trace_mark(subsystem_event, "(int arg, struct
task_struct*task)",
"%d %p", arg, current);How would this work for:
DEFINE_TRACE(sched_switch, (struct task_struct *prev, struct task_struct *next), prev, next);You'd want a string like: "%d %d",
prev->pid,next->pid
not: "%p %p", prev, nextperhaps we can do something like:
Quoted 9 lines
DEFINE_TRACER(sched_switch, (struct
task_struct*prev, structtask_struct*next), prev, next,"%d %d", prev->pid, next->pid);that defines a default tracer function for the previously defined trace point. That way its optional, and allows for generic trace points.
Of course, all this could be ruined by reality - C really sucks wrt forwarding functions.. :-/
Hi Peter,
I've tried to read through the comments recently posted to this thread (sorry I don't have time to answer them all specifically right now, a lot of this makes a lot of sense). I've tried to come up with a proposal, let's name it "tracepoint", which should hopefully address the full scope of the problem. Please tell me if it makes sense. It should allow compile-time verification of dynamically linked-in and activated tracepoints. I'll work on an implementation ASAP.
Mathieu
Tracepoint proposal
- Tracepoint infrastructure
- In-kernel users
- Complete typing, verified by the compiler
- Dynamically linked and activated
- Marker infrastructure
- Exported API to userland
- Basic types only
- Dynamic vs static
- In-kernel probes are dynamically linked, dynamically activated, connected to tracepoints. Type verification is done at compile-time. Those in-kernel probes can be a probe extracting the information to put in a marker or a specific in-kernel tracer such as ftrace.
- Information sinks (LTTng, SystemTAP) are dynamically connected to the markers inserted in the probes and are dynamically activated.
- Near instrumentation site vs in a separate tracer module
A probe module, only if provided with the kernel tree, could connect to internal tracing sites. This argues for keeping the tracepoing probes near the instrumentation site code. However, if a tracer is general purpose and exports typing information to userspace through some mechanism, it should only export the "basic type" information and could be therefore shipped outside of the kernel tree.
In-kernel probes should be integrated to the kernel tree. They would be close to the instrumented kernel code and would translate between the in-kernel instrumentation and the "basic type" exports. Other in-kernel probes could provide a different output (statistics available through debugfs for instance). ftrace falls into this category.
Generic or specialized information "sinks" (LTTng, systemtap) could be connected to the markers put in tracepoint probes to extract the information to userspace. They would extract both typing information and the per-tracepoint execution information to userspace.
Therefore, the code would look like :
kernel/sched.c:
#include "sched-trace.h"
schedule()
{
...
trace_sched_switch(prev, next);
...
}
kernel/sched-trace.h:
DEFINE_TRACE(sched_switch, struct task_struct *prev, struct task_struct *next);
kernel/sched-trace.c:
#include "sched-trace.h"
static probe_sched_switch(struct task_struct *prev, struct task_struct
*next)
{
trace_mark(kernel_sched_switch, "prev_pid %d next_pid %d prev_state %ld",
prev->pid, next->pid, prev->state); }
int __init init(void)
{
return register_sched_switch(probe_sched_switch);
}
void __exit exit(void)
{
unregister_sched_switch(probe_sched_switch);
}
Where DEFINE_TRACE internals declare a structure, a trace_* inline function, a register_trace_* and unregister_trace_* inline functions :
static instrumentation site structure, containing function pointers to deactivated functions and activation boolean. It also contains the "sched_switch" string. This structure is placed in a special section to create an array of these structures.
static inline void trace_sched_switch(struct task_struct *prev,
struct task_struct *next)
{
if (sched_switch tracing is activated)
marshall_probes(&instrumentation_site_structure, prev, next);
}
static inline int register_trace_sched_switch(
void (*probe)(struct task_struct *prev, struct task_struct *next)
{
return do_register_probe("sched_switch", (void *)probe);
}
static inline void unregister_trace_sched_switch(
void (*probe)(struct task_struct *prev, struct task_struct *next)
{
do_unregister_probe("sched_switch", (void *)probe);
}
We need a a new kernel probe API :
do_register_probe / do_unregister_probe
- Connects the in-kernel probe to the site
- Activates the site tracing (probe reference counting)
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC] Tracepoint proposal
Quoted 43 lines · Mathieu Desnoyers
Tracepoint proposal
- Tracepoint infrastructure
- In-kernel users
- Complete typing, verified by the compiler
- Dynamically linked and activated- Marker infrastructure
- Exported API to userland
- Basic types only- Dynamic vs static
- In-kernel probes are dynamically linked, dynamically activated, connected to tracepoints. Type verification is done at compile-time. Those in-kernel probes can be a probe extracting the information to put in a marker or a specific in-kernel tracer such as ftrace.
- Information sinks (LTTng, SystemTAP) are dynamically connected to the markers inserted in the probes and are dynamically activated.- Near instrumentation site vs in a separate tracer module
A probe module, only if provided with the kernel tree, could connect to internal tracing sites. This argues for keeping the tracepoing probes near the instrumentation site code. However, if a tracer is general purpose and exports typing information to userspace through some mechanism, it should only export the "basic type" information and could be therefore shipped outside of the kernel tree.
In-kernel probes should be integrated to the kernel tree. They would be close to the instrumented kernel code and would translate between the in-kernel instrumentation and the "basic type" exports. Other in-kernel probes could provide a different output (statistics available through debugfs for instance). ftrace falls into this category.
Generic or specialized information "sinks" (LTTng, systemtap) could be connected to the markers put in tracepoint probes to extract the information to userspace. They would extract both typing information and the per-tracepoint execution information to userspace.
Therefore, the code would look like :
kernel/sched.c:
Quoted 8 lines
#include "
sched-trace.h"
schedule()
{
...
trace_sched_switch(prev, next);
...
}
Once this is accepted you're going to add hundreds of such calls to every core subsystem, right?
Re: [RFC] Tracepoint proposal
Quoted 53 lines · * Alexey Dobriyan ([email protected]) wrote:
Quoted 43 lines · Mathieu Desnoyers
Tracepoint proposal
- Tracepoint infrastructure
- In-kernel users
- Complete typing, verified by the compiler
- Dynamically linked and activated- Marker infrastructure
- Exported API to userland
- Basic types only- Dynamic vs static
- In-kernel probes are dynamically linked, dynamically activated, connected to tracepoints. Type verification is done at compile-time. Those in-kernel probes can be a probe extracting the information to put in a marker or a specific in-kernel tracer such as ftrace.
- Information sinks (LTTng, SystemTAP) are dynamically connected to the markers inserted in the probes and are dynamically activated.- Near instrumentation site vs in a separate tracer module
A probe module, only if provided with the kernel tree, could connect to internal tracing sites. This argues for keeping the tracepoing probes near the instrumentation site code. However, if a tracer is general purpose and exports typing information to userspace through some mechanism, it should only export the "basic type" information and could be therefore shipped outside of the kernel tree.
In-kernel probes should be integrated to the kernel tree. They would be close to the instrumented kernel code and would translate between the in-kernel instrumentation and the "basic type" exports. Other in-kernel probes could provide a different output (statistics available through debugfs for instance). ftrace falls into this category.
Generic or specialized information "sinks" (LTTng, systemtap) could be connected to the markers put in tracepoint probes to extract the information to userspace. They would extract both typing information and the per-tracepoint execution information to userspace.
Therefore, the code would look like :
kernel/sched.c:Quoted 8 lines
#include "
sched-trace.h"
schedule()
{
...
trace_sched_switch(prev, next);
...
}
Quoted 3 lines
Once this is accepted you're going to add hundreds of such calls to every core subsystem, right?
The LTTng instrumentation has about 125 of such calls. Tests have revealed that adding such dormant tracepoints to the kernel often increase kernel performances rather than decreasing it (see the ia64 benchmarks posted on lkml a few weeks ago).
The core subsystem maintainers are being involved in the process. Actually, marking up the source code has the interesting effect of letting knowledgeable people influence the trace point decisions.
Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC] Tracepoint proposal
Quoted 54 lines · Mathieu Desnoyers
Quoted 53 lines · * Alexey Dobriyan ([email protected]) wrote:
Quoted 51 lines · Mathieu Desnoyers
Tracepoint proposal
- Tracepoint infrastructure
- In-kernel users
- Complete typing, verified by the compiler
- Dynamically linked and activated- Marker infrastructure
- Exported API to userland
- Basic types only- Dynamic vs static
- In-kernel probes are dynamically linked, dynamically activated, connected to tracepoints. Type verification is done at compile-time. Those in-kernel probes can be a probe extracting the information to put in a marker or a specific in-kernel tracer such as ftrace.
- Information sinks (LTTng, SystemTAP) are dynamically connected to the markers inserted in the probes and are dynamically activated.- Near instrumentation site vs in a separate tracer module
A probe module, only if provided with the kernel tree, could connect to internal tracing sites. This argues for keeping the tracepoing probes near the instrumentation site code. However, if a tracer is general purpose and exports typing information to userspace through some mechanism, it should only export the "basic type" information and could be therefore shipped outside of the kernel tree.
In-kernel probes should be integrated to the kernel tree. They would be close to the instrumented kernel code and would translate between the in-kernel instrumentation and the "basic type" exports. Other in-kernel probes could provide a different output (statistics available through debugfs for instance). ftrace falls into this category.
Generic or specialized information "sinks" (LTTng, systemtap) could be connected to the markers put in tracepoint probes to extract the information to userspace. They would extract both typing information and the per-tracepoint execution information to userspace.
Therefore, the code would look like :
kernel/sched.c:#include "
sched-trace.h"
schedule()
{
...
trace_sched_switch(prev, next);
...
}
Quoted 8 lines
Quoted 3 lines
Once this is accepted you're going to add hundreds of such calls to every core subsystem, right?
The LTTng instrumentation has about 125 of such calls. Tests have revealed that adding such dormant tracepoints to the kernel often increase kernel performances rather than decreasing it (see the ia64 benchmarks posted on lkml a few weeks ago).
We're not adding this for performance increase, you do realize this?
Quoted 1 line
The core subsystem maintainers are being involved in the process.
NAK this from proc if you about this.
Quoted 2 lines
Actually, marking up the source code has the interesting effect of letting knowledgeable people influence the trace point decisions.
I'd say that maximum source code overhead any tracing facility should be allowed is "__xxx" annotation at very start of function definition. Anything beyond should be rejected and there are good reasons for that.
Re: [RFC] Tracepoint proposal
Hi Alexey,
Quoted 62 lines · Alexey Dobriyan
Quoted 53 lines · Mathieu Desnoyers
Quoted 52 lines · * Alexey Dobriyan ([email protected]) wrote:
Quoted 51 lines · Mathieu Desnoyers
Tracepoint proposal
- Tracepoint infrastructure
- In-kernel users
- Complete typing, verified by the compiler
- Dynamically linked and activated- Marker infrastructure
- Exported API to userland
- Basic types only- Dynamic vs static
- In-kernel probes are dynamically linked, dynamically activated, connected to tracepoints. Type verification is done at compile-time. Those in-kernel probes can be a probe extracting the information to put in a marker or a specific in-kernel tracer such as ftrace.
- Information sinks (LTTng, SystemTAP) are dynamically connected to the markers inserted in the probes and are dynamically activated.- Near instrumentation site vs in a separate tracer module
A probe module, only if provided with the kernel tree, could connect to internal tracing sites. This argues for keeping the tracepoing probes near the instrumentation site code. However, if a tracer is general purpose and exports typing information to userspace through some mechanism, it should only export the "basic type" information and could be therefore shipped outside of the kernel tree.
In-kernel probes should be integrated to the kernel tree. They would be close to the instrumented kernel code and would translate between the in-kernel instrumentation and the "basic type" exports. Other in-kernel probes could provide a different output (statistics available through debugfs for instance). ftrace falls into this category.
Generic or specialized information "sinks" (LTTng, systemtap) could be connected to the markers put in tracepoint probes to extract the information to userspace. They would extract both typing information and the per-tracepoint execution information to userspace.
Therefore, the code would look like :
kernel/sched.c:#include "
sched-trace.h"
schedule()
{
...
trace_sched_switch(prev, next);
...
}Quoted 7 lines
Quoted 3 lines
Once this is accepted you're going to add hundreds of such calls to every core subsystem, right?
The LTTng instrumentation has about 125 of such calls. Tests have revealed that adding such dormant tracepoints to the kernel often increase kernel performances rather than decreasing it (see the ia64 benchmarks posted on lkml a few weeks ago).
Quoted 5 lines
We're not adding this for performance increase, you do realize this?
Quoted 1 line
The core subsystem maintainers are being involved in the process.
NAK this from proc if you about this.
Hmm, Mathieu, for this issue, I think that no one agrees if there is no clear policy for trace points (for example, subsystem maintainer or patch committer can modify or erase trace points by their patch, if they need; tracepoint maintainers should follow the changes, etc.).
Quoted 6 lines
Quoted 2 lines
Actually, marking up the source code has the interesting effect of letting knowledgeable people influence the trace point decisions.
I'd say that maximum source code overhead any tracing facility should be allowed is "
__xxx" annotation at very start of function definition. Anything beyond should be rejected and there are good reasons for that.
(Out of curiously, would you know any __xxx magic for that?)
One reason why we need markers or other in-the-middle-of-function trace point is that some events happen inside functions, not it's interface.
Actually, we might be able to break those functions into several functions to export it's interface to tracers. However, I think it is easier to call trace_XXX than that.
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
RE: [RFC] Tracepoint proposal
Hi
Quoted 3 lines · Hiramatsu
One reason why we need markers or other in-the-middle-of-function trace point is that some events happen inside functions, not it's interface.
Each kernel sub-system seems to have its own way of dealing with
debugging statements. Some of these methods include 'dprintk', 'pr_debug', 'dev_debug', 'DEBUGP'. I think that these functions are the tracepoints that has been availably mounted without setting up the tool set of the outside. I think whether mounting that unites these functions can be done if kernel marker and tracepoint are used.
By the way, isn't there problem on security?
What kprobe, jprobe, and kernel marker, etc. offer looks like what
the framework of Linux Security Module had offered before. Gotten kprobe, jprobe, and kernel marker, etc. should not be exported to the userland for security because it becomes the hotbed of rootkits. Users such as kprobe, jprobe, and kernel marker should not be Loadable Kernel Module. I think that there are some solutions in LTTng about this security problem. However, will the environment to be able to operate SystemTap be really secure?
At least, kernel commandline option to invalidate all of kprobe, jprobe, and kernel marker, etc. because of the batch might be necessary.
Thank you,
--
Takashi Nishiie
Re: [RFC] Tracepoint proposal
Quoted 7 lines · Takashi Nishiie
[...]
Each kernel sub-system seems to have its own way of dealing with debugging statements. Some of these methods include 'dprintk', 'pr_debug', 'dev_debug', 'DEBUGP'. I think that these functions are the tracepoints that has been availably mounted without setting up the tool set of the outside. I think whether mounting that unites these functions can be done if kernel marker and tracepoint are used.
There are efforts underway to collect these various debug methods into a single run-time-dynamic stream, which may even turn out to connect to markers.
Quoted 5 lines
By the way, isn't there problem on security? What kprobe, jprobe, and kernel marker, etc. offer looks like what the framework of Linux Security Module had offered before. Gotten kprobe, jprobe, and kernel marker, etc. should not be exported to the userland for security because it becomes the hotbed of rootkits.
These are all kernel-side facilities with no direct connection to user-land.
Quoted 2 lines
Users such as kprobe, jprobe, and kernel marker should not be Loadable Kernel Module. [...]
That would defeat their usefulness. Remember, kernel modules run with no hardware-level restrictions at all, so if an adversary managed to load up some kernel malware module, the game is over, whether or not they use kprobes.
- FChE
Re: [RFC] Tracepoint proposal
In reply to Takashi NishiieHi,
Quoted 7 lines · Takashi Nishiie
Hi
Quoted 3 lines · Hiramatsu
One reason why we need markers or other in-the-middle-of-function trace point is that some events happen inside functions, not it's interface.
Quoted 6 lines
Each kernel sub-system seems to have its own way of dealing with
debugging statements. Some of these methods include 'dprintk', 'pr_debug', 'dev_debug', 'DEBUGP'. I think that these functions are the tracepoints that has been availably mounted without setting up the tool set of the outside. I think whether mounting that unites these functions can be done if kernel marker and tracepoint are used.
Sure, I think those functions covers each partially, but some requirements are different.
dynamic printk
- stored in a section
- dynamic activation
- formatted message (multiple messages for each activation group)
- export basic types
- variadic function
- low frequently called
- module support
Marker
- stored in a section
- dynamic activation
- formatted string (single format for each marker)
- export basic types
- variadic function
- low-high frequently called
- module support
Tracepoint
- stored in a section
- dynamic activation
- no message
- export kernel structure
- arguments depending on points
- high frequently called
- no module support (kernel use only)
Quoted 4 lines
By the way, isn't there problem on security?
What kprobe, jprobe, and kernel marker, etc. offer looks like what
the framework of Linux Security Module had offered before. Gotten kprobe, jprobe, and kernel marker, etc. should not be exported to the
Quoted 8 lines
userland for security because it becomes the hotbed of rootkits. Users such as kprobe, jprobe, and kernel marker should not be Loadable Kernel Module. I think that there are some solutions in LTTng about this security problem. However, will the environment to be able to operate SystemTap be really secure?
At least, kernel commandline option to invalidate all of kprobe, jprobe, and kernel marker, etc. because of the batch might be necessary.
Please, set CONFIG_MODULES=no.
If your system really really needs to be hardened, please don't make kernel module loadable. Otherwise, any kernel module can modify any kernel code. So, I think it's not a problem of any specific functionality.
Anyway, I think selinux will give you more flexible way to restrict who can load what modules.
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC] Tracepoint proposal
Quoted 8 lines
Tracepoint
- stored in a section
- dynamic activation
- no message
- export kernel structure
- arguments depending on points
- high frequently called
- no module support (kernel use only)
Why Shouldn't kernel module use tracepoint?
technical problem? or any plicy exist?
Re: [RFC] Tracepoint proposal
Quoted 11 lines · KOSAKI Motohiro
Quoted 8 lines
Tracepoint
- stored in a section
- dynamic activation
- no message
- export kernel structure
- arguments depending on points
- high frequently called
- no module support (kernel use only)Why Shouldn't kernel module use tracepoint?
technical problem? or any plicy exist?
Good question, I think we don't want to export so much kernel internal structures. Since tracepoint tend to export raw kernel structure to user module, I thought it might be better not to export its interface to modules.
However, I thought that again, and knew what Peter worried was about marker which exports marker list to user space. So, the issue is exporting internal structures to user space, not to modules. Thus, I think it can support modules also.
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC] Tracepoint proposal
Quoted 18 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 11 lines · KOSAKI Motohiro
Quoted 8 lines
Tracepoint
- stored in a section
- dynamic activation
- no message
- export kernel structure
- arguments depending on points
- high frequently called
- no module support (kernel use only)Why Shouldn't kernel module use tracepoint?
technical problem? or any plicy exist?Good question, I think we don't want to export so much kernel internal structures. Since tracepoint tend to export raw kernel structure to user module, I thought it might be better not to export its interface to modules.
Quoted 5 lines
However, I thought that again, and knew what Peter worried was about marker which exports marker list to user space. So, the issue is exporting internal structures to user space, not to modules. Thus, I think it can support modules also.
Agreed. It could be good to someday merge these tracepoint probes with the mainline kernel so they can easily be adapted to tracepoint changes. It seems correct to me for tracepoint probes to be either in the core kernel or in modules, but I expect that they will be easier to maintain within the tree.
Mathieu
Quoted 11 lines
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
RFC PATCH 1/1 Kernel Tracepoints
In reply to Masami Hiramatsu** note : this patch is submitted for early review. It applies after my current unreleased 2.6.26-rc8 LTTng patchset. Comments are welcome.
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
Allows complete typing verification. No format string required.
TODO : Documentation/tracepoint.txt
--- include/asm-generic/vmlinux.lds.h | 4 include/linux/module.h | 17 + include/linux/tracepoint.h | 154 +++++++++++ init/Kconfig | 7 kernel/Makefile | 1 kernel/module.c | 71 +++++ kernel/tracepoint.c | 495 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 748 insertions(+), 1 deletion(-)
init/Kconfig +7 -0
@@ -782,6 +782,13 @@ Say Y here to enable the extended profiling support mechanisms used by profilers such as OProfile. +config TRACEPOINTS + bool "Activate tracepoints" + default y + help + Place an empty function call at each tracepoint site. Can be + dynamically changed for a probe function. + config MARKERS bool "Activate markers" help
kernel/Makefile +1 -0
@@ -69,6 +69,7 @@ obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o obj-$(USE_IMMEDIATE) += immediate.o obj-$(CONFIG_MARKERS) += marker.o +obj-$(CONFIG_TRACEPOINTS) += tracepoint.o obj-$(CONFIG_LATENCYTOP) += latencytop.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
include/linux/tracepoint.h new file +154 -0
154 lines not on this page · raw message
include/asm-generic/vmlinux.lds.h +4 -0
@@ -53,6 +53,9 @@ VMLINUX_SYMBOL(__start___markers) = .; \ *(__markers ) \ VMLINUX_SYMBOL(__stop___markers) = .; \ + VMLINUX_SYMBOL(__start___tracepoints) = .; \ + *(__tracepoints ) \ + VMLINUX_SYMBOL(__stop___tracepoints) = .; \ VMLINUX_SYMBOL(__start___imv) = .; \ *(__imv )/* Immediate values: pointers */ \ VMLINUX_SYMBOL(__stop___imv) = .;
@@ -68,6 +71,7 @@ *(__imv_cond_end )/* Immediate condition end pointers */ \ VMLINUX_SYMBOL(__stop___imv_cond_end) = .; \ *(__markers_strings)/* Markers: strings */ \ + *(__tracepoints_strings)/* Tracepoints: strings */ \ } \ \ .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
kernel/tracepoint.c new file +495 -0
495 lines not on this page · raw message
kernel/module.c +70 -1
108 lines not on this page · raw message
include/linux/module.h +17 -0
@@ -17,6 +17,7 @@#include <linux/moduleparam.h> #include <linux/immediate.h> #include <linux/marker.h> +#include <linux/tracepoint.h> #include <asm/local.h> #include <asm/module.h>
@@ -349,6 +350,10 @@struct marker *markers;unsigned int num_markers;#endif +#ifdef CONFIG_TRACEPOINTS +struct tracepoint *tracepoints; +unsigned int num_tracepoints; +#endif };#ifndef MODULE_ARCH_INIT #define MODULE_ARCH_INIT {}
@@ -459,6 +464,9 @@extern void module_update_markers (void );extern int module_get_iter_markers (struct marker_iter *iter); +extern void module_update_tracepoints (void ); +extern int module_get_iter_tracepoints (struct tracepoint_iter *iter); +#else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym)#define EXPORT_SYMBOL_GPL (sym)
@@ -568,6 +576,15 @@ return 0; } +static inline void module_update_tracepoints (void ) +{ +} + +static inline int module_get_iter_tracepoints (struct tracepoint_iter *iter) +{ +return 0 ; +} +#endif /* CONFIG_MODULES */ #if defined(CONFIG_MODULES ) && defined(USE_IMMEDIATE )
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints
Hi Mathieu,
Thank you for making this so soon!
Quoted 2 lines · Mathieu Desnoyers
** note : this patch is submitted for early review. It applies after my current unreleased 2.6.26-rc8 LTTng patchset. Comments are welcome.
Would you mean there is no tree on which we can test this patch?
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
For example, (not complete, I just thought :-))
struct tracepoint {
const char *name; /* Tracepoint name */
DEFINE_IMV(char, state); /* Immediate value state. */
struct tracepoint_probe_closure *multi; /* Closures */
void * callsite_data; /* private date from call site */
} __attribute__((aligned(8)));
#define __tracepoint_block(generic, name, data, func, args)
static const char __tpstrtab_##name[] \
__attribute__((section("__tracepoints_strings"))) \
= #name; \
static struct tracepoint __tracepoint_##name \
__attribute__((section("__tracepoints"), aligned(8))) = \
{ __tpstrtab_##name, 0, NULL, data}; \
if (!generic) { \
if (unlikely(imv_cond(__tracepoint_##name.state))) { \
imv_cond_end(); \
func(&__tracepoint_##name, args); \
} else \
imv_cond_end(); \
} else { \
if (unlikely(_imv_read(__tracepoint_##name.state))) \
func(&__tracepoint_##name, args); \
}
struct marker {
const char *name; /* Marker name */
const char *format; /* Marker format string, describing the
* variable argument list. */
} __attribute__((aligned(8)));
#define trace_mark(name, fmt, args...) \
do { \
static const char __mstrtab_##name[] \
__attribute__((section("__markers_strings"))) \
= #name "\0" fmt; \
static struct marker __marker_##name \
__attribute__((section("__markers"), aligned(8))) = \
{ __mstrtab_##name, &__mstrtab_##name[sizeof(#name)]}; \
__tracepoint_block(1, name, __marker_##name, marker_probe_cb, args) \
} while (0)
Quoted 4 lines
Allows complete typing verification. No format string required.
TODO :
Documentation/tracepoint.txt
[...]
Quoted 6 lines
+/*
+ * Note : the empty asm volatile with read constraint is used here instead of a
+ * "used" attribute to fix a gcc 4.1.x bug.as
+ * Make sure the alignment of the structure in the__markerssection will
+ * not add unwanted padding between the beginning of the section and the
+ * structure. Force alignment to the same alignment as the section start.
this comment should be updated...
Quoted 52 lines
+ *
+ * The "generic" argument controls which marker enabling mechanism must be used.
+ * If generic is true, a variable read is used.
+ * If generic is false, immediate values are used.
+ */include/linux/tracepoint.h new file +47
-0+#define DEFINE_TRACE (name, proto, args) \ + static inline void _do_trace_##name(struct tracepoint *tp, proto) \ + { \ + int i; \ + struct tracepoint_probe_closure *multi; \ + preempt_disable(); \ + multi = tp->multi; \ + smp_read_barrier_depends(); \ + if (multi) { \ + for (i = 0; multi[i].func; i++) { \ + ((void(*)(void *private_data, proto)) \ + (multi[i].func))(multi[i].probe_private, args);\ + } \ + } \ + preempt_enable(); \ + } \ + static inline void __trace_##name(int generic, proto) \ + { \ + static const char __tpstrtab_##name[] \ + __attribute__((section("__tracepoints_strings"))) \ + = #name; \ + static struct tracepoint __tracepoint_##name \ + __attribute__((section("__tracepoints"), aligned(8))) = \ + { __tpstrtab_##name, 0, NULL }; \ + if (!generic) { \ + if (unlikely(imv_cond(__tracepoint_##name.state))) { \ + imv_cond_end(); \ + _do_trace_##name(&__tracepoint_##name, args); \ + } else \ + imv_cond_end(); \ + } else { \ + if (unlikely(_imv_read(__tracepoint_##name.state))) \ + _do_trace_##name(&__tracepoint_##name, args); \ + } \ + } \ + static inline void trace_##name(proto) \ + { \ + __trace_##name(0, args); \ + } \ + static inline void _trace_##name(proto) \ + { \ + __trace_##name(1, args); \ + } \ + static inline int register_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \
include/linux/tracepoint.h line 107
Quoted 10 lines
include/linux/tracepoint.h new file +10
-0+ return tracepoint_probe_register(#name, (void *)probe, \ + private_data); \ + } \ + static inline void unregister_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \ + tracepoint_probe_unregister(#name, (void *)probe, \ + private_data); \ + }
Out of curiousity, what the private_data is for?
Quoted 4 lines
include/linux/tracepoint.h new file +4
-0+ +extern void tracepoint_update_probe_range (struct tracepoint *begin, +struct tracepoint *end); +
include/linux/tracepoint.h line 121
Quoted 10 lines
include/linux/tracepoint.h new file +10
-0+#else /* !CONFIG_TRACEPOINTS */ +#define DEFINE_TRACE (name, proto, args) \ + static inline void _do_trace_##name(struct tracepoint *tp, proto) \ + { } \ + static inline void __trace_##name(int generic, proto) \ + { } \ + static inline void trace_##name(proto) \ + { } \ + static inline void _trace_##name(proto) \ + { }
By the way, I think you'd better add below two inlines.
static inline int register_trace_##name( \
void (*probe)(void *private_data, proto), \
void *private_data) \
{ return -ENOSYS; }
static inline void unregister_trace_##name( \
void (*probe)(void *private_data, proto), \
void *private_data) \
{ }Quoted 23 lines
include/linux/tracepoint.h new file +23
-0+ +static inline void tracepoint_update_probe_range (struct tracepoint *begin, +struct tracepoint *end) +{ } +#endif /* CONFIG_TRACEPOINTS */ + +/* +* Connect a probe to a tracepoint. +* Internal API, should not be used directly. +*/ +extern int tracepoint_probe_register (const char *name, +void *probe,void *probe_private); + +/* +* Disconnect a probe from a tracepoint. +* Internal API, should not be used directly. +*/ +extern int tracepoint_probe_unregister (const char *name, +void *probe,void *probe_private); + +struct tracepoint_iter { +struct module *module; +struct tracepoint *tracepoint;
include/linux/tracepoint.h line 154
Quoted 10 lines
include/linux/tracepoint.h new file +10
-0+}; + +extern void tracepoint_iter_start (struct tracepoint_iter *iter); +extern void tracepoint_iter_next (struct tracepoint_iter *iter); +extern void tracepoint_iter_stop (struct tracepoint_iter *iter); +extern void tracepoint_iter_reset (struct tracepoint_iter *iter); +extern int tracepoint_get_iter_range (struct tracepoint **tracepoint, +struct tracepoint *begin,struct tracepoint *end); + +#endif
[...]
Best regards,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC PATCH] Kernel Tracepoints
Quoted 4 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
Thank you for making this so soon!
Hi Masami,
Thanks for the comments, I will rework the patch accordingly.
Also, one thing I thought about yesterday which I dislike is that if we have two modules declaring the same tracepoint in different headers with different prototypes, each declaration will be valid but the registration will try to connect a probe expecting wrong parameters to the other tracepoint.
It would be the case if someone does :
drivers/somedrivera/mydriver1-trace.h
DECLARE_TRACE(really_generic_name, TPPTOTO(void), TPARGS()));
drivers/somedriverb/mydriver2-trace.h
DECLARE_TRACE(really_generic_name, TPPTOTO(struct somestruct *s), TPARGS(s)));
Do you think it's worth it to append the prototype string to the tracepoint name ? I think it should fix the problem.
Mathieu
Quoted 211 lines
Quoted 2 lines · Mathieu Desnoyers
** note : this patch is submitted for early review. It applies after my current unreleased 2.6.26-rc8 LTTng patchset. Comments are welcome.
Would you mean there is no tree on which we can test this patch?
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
For example, (not complete, I just thought :-))
struct tracepoint {
(quoted diff) +0
-0const char *name; /* Tracepoint name */ DEFINE_IMV(char, state); /* Immediate value state. */ struct tracepoint_probe_closure *multi; /* Closures */void *
callsite_data; /* private date from call site */
} __attribute__((aligned(8)));#define
__tracepoint_block(generic, name, data, func, args)(quoted diff) +0
-0static const char __tpstrtab_##name[] \ __attribute__((section("__tracepoints_strings"))) \ = #name; \ static struct tracepoint __tracepoint_##name \ __attribute__((section("__tracepoints"), aligned(8))) = \ { __tpstrtab_##name, 0, NULL, data}; \ if (!generic) { \ if (unlikely(imv_cond(__tracepoint_##name.state))) { \ imv_cond_end(); \ func(&__tracepoint_##name, args); \ } else \ imv_cond_end(); \ } else { \ if (unlikely(_imv_read(__tracepoint_##name.state))) \ func(&__tracepoint_##name, args); \ } struct marker { const char *name; /* Marker name */ const char *format; /* Marker format string, describing the * variable argument list. */ } __attribute__((aligned(8))); #define trace_mark(name, fmt, args...) \ do { \ static const char __mstrtab_##name[] \ __attribute__((section("__markers_strings"))) \ = #name "\0" fmt; \ static struct marker __marker_##name \ __attribute__((section("__markers"), aligned(8))) = \ { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)]}; \ __tracepoint_block(1, name, __marker_##name, marker_probe_cb, args) \ } while (0)Quoted 5 lines
Allows complete typing verification. No format string required.
TODO :
Documentation/tracepoint.txt[...]
Quoted 6 lines
+/*
+ * Note : the empty asm volatile with read constraint is used here instead of a
+ * "used" attribute to fix a gcc 4.1.x bug.as
+ * Make sure the alignment of the structure in the__markerssection will
+ * not add unwanted padding between the beginning of the section and the
+ * structure. Force alignment to the same alignment as the section start.this comment should be updated...
Quoted 52 lines
+ *
+ * The "generic" argument controls which marker enabling mechanism must be used.
+ * If generic is true, a variable read is used.
+ * If generic is false, immediate values are used.
+ */include/linux/tracepoint.h new file +47
-0+#define DEFINE_TRACE (name, proto, args) \ + static inline void _do_trace_##name(struct tracepoint *tp, proto) \ + { \ + int i; \ + struct tracepoint_probe_closure *multi; \ + preempt_disable(); \ + multi = tp->multi; \ + smp_read_barrier_depends(); \ + if (multi) { \ + for (i = 0; multi[i].func; i++) { \ + ((void(*)(void *private_data, proto)) \ + (multi[i].func))(multi[i].probe_private, args);\ + } \ + } \ + preempt_enable(); \ + } \ + static inline void __trace_##name(int generic, proto) \ + { \ + static const char __tpstrtab_##name[] \ + __attribute__((section("__tracepoints_strings"))) \ + = #name; \ + static struct tracepoint __tracepoint_##name \ + __attribute__((section("__tracepoints"), aligned(8))) = \ + { __tpstrtab_##name, 0, NULL }; \ + if (!generic) { \ + if (unlikely(imv_cond(__tracepoint_##name.state))) { \ + imv_cond_end(); \ + _do_trace_##name(&__tracepoint_##name, args); \ + } else \ + imv_cond_end(); \ + } else { \ + if (unlikely(_imv_read(__tracepoint_##name.state))) \ + _do_trace_##name(&__tracepoint_##name, args); \ + } \ + } \ + static inline void trace_##name(proto) \ + { \ + __trace_##name(0, args); \ + } \ + static inline void _trace_##name(proto) \ + { \ + __trace_##name(1, args); \ + } \ + static inline int register_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \include/linux/tracepoint.h line 107
Quoted 10 lines
include/linux/tracepoint.h new file +10
-0+ return tracepoint_probe_register(#name, (void *)probe, \ + private_data); \ + } \ + static inline void unregister_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \ + tracepoint_probe_unregister(#name, (void *)probe, \ + private_data); \ + }Out of curiousity, what the
private_datais for?Quoted 4 lines
include/linux/tracepoint.h new file +4
-0+ +extern void tracepoint_update_probe_range (struct tracepoint *begin, +struct tracepoint *end); +include/linux/tracepoint.h line 121
Quoted 10 lines
include/linux/tracepoint.h new file +10
-0+#else /* !CONFIG_TRACEPOINTS */ +#define DEFINE_TRACE (name, proto, args) \ + static inline void _do_trace_##name(struct tracepoint *tp, proto) \ + { } \ + static inline void __trace_##name(int generic, proto) \ + { } \ + static inline void trace_##name(proto) \ + { } \ + static inline void _trace_##name(proto) \ + { }By the way, I think you'd better add below two inlines.
static inline int register_trace_##name( \ void (*probe)(void *private_data, proto), \ void *private_data) \ { return -ENOSYS; } static inline void unregister_trace_##name( \ void (*probe)(void *private_data, proto), \ void *private_data) \ { }Quoted 23 lines
include/linux/tracepoint.h new file +23
-0+ +static inline void tracepoint_update_probe_range (struct tracepoint *begin, +struct tracepoint *end) +{ } +#endif /* CONFIG_TRACEPOINTS */ + +/* +* Connect a probe to a tracepoint. +* Internal API, should not be used directly. +*/ +extern int tracepoint_probe_register (const char *name, +void *probe,void *probe_private); + +/* +* Disconnect a probe from a tracepoint. +* Internal API, should not be used directly. +*/ +extern int tracepoint_probe_unregister (const char *name, +void *probe,void *probe_private); + +struct tracepoint_iter { +struct module *module; +struct tracepoint *tracepoint;include/linux/tracepoint.h line 154
Quoted 10 lines
include/linux/tracepoint.h new file +10
-0+}; + +extern void tracepoint_iter_start (struct tracepoint_iter *iter); +extern void tracepoint_iter_next (struct tracepoint_iter *iter); +extern void tracepoint_iter_stop (struct tracepoint_iter *iter); +extern void tracepoint_iter_reset (struct tracepoint_iter *iter); +extern int tracepoint_get_iter_range (struct tracepoint **tracepoint, +struct tracepoint *begin,struct tracepoint *end); + +#endif [...]
Best regards,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints
Quoted 23 lines · Mathieu Desnoyers
Quoted 4 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
Thank you for making this so soon!
Hi Masami,
Thanks for the comments, I will rework the patch accordingly.
Also, one thing I thought about yesterday which I dislike is that if we have two modules declaring the same tracepoint in different headers with different prototypes, each declaration will be valid but the registration will try to connect a probe expecting wrong parameters to the other tracepoint.
It would be the case if someone does :
drivers/somedrivera/mydriver1-trace.h
DECLARE_TRACE(really_generic_name, TPPTOTO(void), TPARGS()));
Quoted 6 lines
drivers/somedriverb/mydriver2-trace.h
DECLARE_TRACE(really_generic_name, TPPTOTO(struct somestruct *s), TPARGS(s)));Do you think it's worth it to append the prototype string to the tracepoint name ? I think it should fix the problem.
Hmm, I think we'd better send a fix patch to them in that case. (I hope we can find that kind of conflicts soon)
I think we can make an external tool which detect those conflicts. Anyway, signature based checking idea is good to me. I think ":" is better delimiter.
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC PATCH] Kernel Tracepoints
Quoted 28 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 25 lines · Mathieu Desnoyers
Quoted 4 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
Thank you for making this so soon!
Hi Masami,
Thanks for the comments, I will rework the patch accordingly.
Also, one thing I thought about yesterday which I dislike is that if we have two modules declaring the same tracepoint in different headers with different prototypes, each declaration will be valid but the registration will try to connect a probe expecting wrong parameters to the other tracepoint.
It would be the case if someone does :
drivers/somedrivera/mydriver1-trace.h
DECLARE_TRACE(really_generic_name, TPPTOTO(void), TPARGS()));
drivers/somedriverb/mydriver2-trace.h
Quoted 8 lines
Quoted 4 lines
DECLARE_TRACE(really_generic_name, TPPTOTO(struct somestruct *s), TPARGS(s)));Do you think it's worth it to append the prototype string to the tracepoint name ? I think it should fix the problem.
Hmm, I think we'd better send a fix patch to them in that case. (I hope we can find that kind of conflicts soon)
I think we can make an external tool which detect those conflicts.
Hrm, ideally, we could output this information in a file which looks like the Marker file generated by depmod, and automatically check for duplicate tracepoints with different prototypes. That should also deal with modules built outside of the kernel tree.
Quoted 2 lines
Anyway, signature based checking idea is good to me. I think ":" is better delimiter.
Yes, changing it for :.
If we append the prototype to the tracepoint name, then at least we can later add the consistency check in depmod.
Mathieu
Quoted 14 lines
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints
In reply to Masami HiramatsuQuoted 10 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
Thank you for making this so soon!
Quoted 2 lines · Mathieu Desnoyers
** note : this patch is submitted for early review. It applies after my current unreleased 2.6.26-rc8 LTTng patchset. Comments are welcome.
Would you mean there is no tree on which we can test this patch?
It actually applies on top of the following patchset :
http://ltt.polymtl.ca/lttng/patch-2.6.26-rc8-0.10-pre56.tar.bz2
Thanks,
Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints
Hi Mathieu,
Quoted 6 lines · Mathieu Desnoyers
Quoted 5 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
Thank you for making this so soon!
Mathieu Desnoyers wrote:
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
** note : this patch is submitted for early review. It applies after my current unreleased 2.6.26-rc8 LTTng patchset. Comments are welcome.
Would you mean there is no tree on which we can test this patch?
It actually applies on top of the following patchset :
http://ltt.polymtl.ca/lttng/patch-2.6.26-rc8-0.10-pre56.tar.bz2
Thank you,
I think, this tracepoint patch might be better moved before immediate and LTTng's marking point patches, because current -mm/-next tree doesn't have immediate, and all marking points are replaced by tracepoints.
Regards,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC PATCH] Kernel Tracepoints
In reply to Masami HiramatsuQuoted 7 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
We could, although markers, because they use var args, allow to put the iteration on the multi probe array out-of-line. Tracepoints cannot afford this and the iteration must be done at the initial call-site.
Quoted 1 line
From what I see in your proposal, it's mostly to extract the
if()call()
code from the inner __trace_mark() macro and to put it in a separate macro, am I correct ? This would make the macro more readable.
Quoted 46 lines
For example, (not complete, I just thought :-))
struct tracepoint {
(quoted diff) +0
-0const char *name; /* Tracepoint name */ DEFINE_IMV(char, state); /* Immediate value state. */ struct tracepoint_probe_closure *multi; /* Closures */void *
callsite_data; /* private date from call site */
} __attribute__((aligned(8)));#define
__tracepoint_block(generic, name, data, func, args)(quoted diff) +0
-0static const char __tpstrtab_##name[] \ __attribute__((section("__tracepoints_strings"))) \ = #name; \ static struct tracepoint __tracepoint_##name \ __attribute__((section("__tracepoints"), aligned(8))) = \ { __tpstrtab_##name, 0, NULL, data}; \ if (!generic) { \ if (unlikely(imv_cond(__tracepoint_##name.state))) { \ imv_cond_end(); \ func(&__tracepoint_##name, args); \ } else \ imv_cond_end(); \ } else { \ if (unlikely(_imv_read(__tracepoint_##name.state))) \ func(&__tracepoint_##name, args); \ } struct marker { const char *name; /* Marker name */ const char *format; /* Marker format string, describing the * variable argument list. */ } __attribute__((aligned(8))); #define trace_mark(name, fmt, args...) \ do { \ static const char __mstrtab_##name[] \ __attribute__((section("__markers_strings"))) \ = #name "\0" fmt; \ static struct marker __marker_##name \ __attribute__((section("__markers"), aligned(8))) = \ { __mstrtab_##name, &__mstrtab_##name[sizeof(#name)]}; \ __tracepoint_block(1, name, __marker_##name, marker_probe_cb, args) \ } while (0)Quoted 2 lines
[...]
Quoted 8 lines
Quoted 8 lines
include/linux/tracepoint.h new file +8
-0+ static inline int register_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \ + return tracepoint_probe_register(#name, (void *)probe, \ + private_data); \ + } \ + static inline void unregister_trace_##name( \
Quoted 9 lines
include/linux/tracepoint.h line 107
Quoted 6 lines
include/linux/tracepoint.h new file +6
-0+void (*probe)(void *private_data,proto ), \ + void *private_data) \ + { \ + tracepoint_probe_unregister(#name, (void *)probe, \ +private_data ); \ + }Out of curiousity, what the
private_datais for?
When a probe is registered, it gives more flexibility to be able to pass a pointer to private data associated with that probe. For instance, if a tracer needs to register the same probe to many different tracepoints, but having a different context associated with each, it will pass the same function pointer with different private_data to the registration function.
Quoted 17 lines
Quoted 4 lines
include/linux/tracepoint.h new file +4
-0+ +extern void tracepoint_update_probe_range (struct tracepoint *begin, +struct tracepoint *end); +include/linux/tracepoint.h line 121
Quoted 10 lines
include/linux/tracepoint.h new file +10
-0+#else /* !CONFIG_TRACEPOINTS */ +#define DEFINE_TRACE (name, proto, args) \ + static inline void _do_trace_##name(struct tracepoint *tp, proto) \ + { } \ + static inline void __trace_##name(int generic, proto) \ + { } \ + static inline void trace_##name(proto) \ + { } \ + static inline void _trace_##name(proto) \ + { }By the way, I think you'd better add below two inlines.
Quoted 9 lines
static inline int register_trace_##name( \
void (*probe)(void *private_data, proto), \
void *private_data) \
{ return -ENOSYS; }
static inline void unregister_trace_##name( \
void (*probe)(void *private_data, proto), \
void *private_data) \
{ }My original thought was that if tracepoints are disabled, the probe objects should not even be built. But I can foresee that they will not always be in separate objects, so it makes sense. Will add.
Thanks,
Mathieu
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints
Quoted 8 lines · Mathieu Desnoyers
Quoted 6 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
Quoted 7 lines
We could, although markers, because they use var args, allow to put the iteration on the multi probe array out-of-line. Tracepoints cannot afford this and the iteration must be done at the initial call-site.
From what I see in your proposal, it's mostly to extract the
if()call()code from the inner__trace_mark()macro and to put it in a separate macro, am I correct ? This would make the macro more readable.
Sure, I think marker and tracepoint can share below functions;
- definition of static local variables in specific sections
- probe activation code (if() call())
- multi probe handling
Then, marker just exports marker_strings sections.
Quoted 18 lines
Quoted 18 lines
For example, (not complete, I just thought :-))
struct tracepoint {
(quoted diff) +0
-0const char *name; /* Tracepoint name */ DEFINE_IMV(char, state); /* Immediate value state. */ struct tracepoint_probe_closure *multi; /* Closures */void *
callsite_data; /* private date from call site */
} __attribute__((aligned(8)));#define
__tracepoint_block(generic, name, data, func, args)(quoted diff) +0
-0static const char __tpstrtab_##name[] \ __attribute__((section("__tracepoints_strings"))) \ = #name; \ static struct tracepoint __tracepoint_##name \ __attribute__((section("__tracepoints"), aligned(8))) = \ { __tpstrtab_##name, 0, NULL, data}; \ if (!generic) { \ if (unlikely(imv_cond(__tracepoint_##name.state))) { \
Quoted 8 lines
Review
Quoted 8 lines
(quoted diff) +0
-0imv_cond_end(); \ func(&__tracepoint_##name, args); \ } else \ imv_cond_end(); \ } else { \ if (unlikely(_imv_read(__tracepoint_##name.state))) \ func(&__tracepoint_##name, args); \ }
So, in my idea, __trace_##name() also uses __tracepoint_block() for avoiding code duplication.
Quoted 18 lines
[...]
Quoted 7 lines
Quoted 7 lines
include/linux/tracepoint.h new file +7
-0+ static inline int register_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \ + return tracepoint_probe_register(#name, (void *)probe, \ + private_data); \ + } \Quoted 9 lines
include/linux/tracepoint.h line 107
Quoted 7 lines
include/linux/tracepoint.h new file +7
-0+ static inline void unregister_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \ + tracepoint_probe_unregister(#name, (void *)probe, \ + private_data); \ + }Out of curiousity, what the
private_datais for?
Quoted 6 lines
When a probe is registered, it gives more flexibility to be able to pass a pointer to private data associated with that probe. For instance, if a tracer needs to register the same probe to many different tracepoints, but having a different context associated with each, it will pass the same function pointer with different
private_datato the registration function.
Hmm, only for tracepoint, it might be not so useful, because most of tracepoint's prototypes are different and so we can't use same probe to those tracepoints.
Anyway, it is useful for more general probe(ex. markers) if that is implemented on tracepoint ;-)
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC PATCH] Kernel Tracepoints
Quoted 13 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 12 lines · Mathieu Desnoyers
Quoted 6 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
We could, although markers, because they use var args, allow to put the iteration on the multi probe array out-of-line. Tracepoints cannot afford this and the iteration must be done at the initial call-site.
Quoted 6 lines
Quoted 3 lines
From what I see in your proposal, it's mostly to extract the
if()call()code from the inner__trace_mark()macro and to put it in a separate macro, am I correct ? This would make the macro more readable.Sure, I think marker and tracepoint can share below functions;
- definition of static local variables in specific sections
Given that we could want to keep activation of tracepoints and markers separate (so they don't share the same namespace), declaring the static variables in separated sections seems to make sense to me.
Quoted 2 lines
- probe activation code (
if()call())
- multi probe handling
Hrm, the thing here is that because markers allow to do the iteration on the multiple probe callbacks within an internal wrapper (instead of doing it on-site as in the tracepoints), it allows to do some further optimizations (less memory allocation and less pointer dereference in the single probe case, not having to prepare the va_args in the MARK_NOARGS case) which are only done because it does not have to add code to the instrumentation site. However, tracepoints cannot have such "generic" wrapper and we have to do the iteration on callbacks in the code added to the instrumented object. Therefore, I keep it as small as possible in terms of bytes of instructions.
Quoted 59 lines
Then, marker just exports
marker_stringssections.Quoted 18 lines
Quoted 18 lines
For example, (not complete, I just thought :-))
struct tracepoint {
(quoted diff) +0
-0const char *name; /* Tracepoint name */ DEFINE_IMV(char, state); /* Immediate value state. */ struct tracepoint_probe_closure *multi; /* Closures */void *
callsite_data; /* private date from call site */
} __attribute__((aligned(8)));#define
__tracepoint_block(generic, name, data, func, args)(quoted diff) +0
-0static const char __tpstrtab_##name[] \ __attribute__((section("__tracepoints_strings"))) \ = #name; \ static struct tracepoint __tracepoint_##name \ __attribute__((section("__tracepoints"), aligned(8))) = \ { __tpstrtab_##name, 0, NULL, data}; \ if (!generic) { \ if (unlikely(imv_cond(__tracepoint_##name.state))) { \Quoted 8 lines
Review
Quoted 8 lines
(quoted diff) +0
-0imv_cond_end(); \ func(&__tracepoint_##name, args); \ } else \ imv_cond_end(); \ } else { \ if (unlikely(_imv_read(__tracepoint_##name.state))) \ func(&__tracepoint_##name, args); \ }So, in my idea, __trace_##name() also uses
__tracepoint_block()for avoiding code duplication.Quoted 18 lines
[...]
Quoted 7 lines
Quoted 7 lines
include/linux/tracepoint.h new file +7
-0+ static inline int register_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \ + return tracepoint_probe_register(#name, (void *)probe, \ + private_data); \ + } \Quoted 9 lines
include/linux/tracepoint.h line 107
Quoted 7 lines
include/linux/tracepoint.h new file +7
-0+ static inline void unregister_trace_##name( \ + void (*probe)(void *private_data, proto), \ + void *private_data) \ + { \ + tracepoint_probe_unregister(#name, (void *)probe, \ + private_data); \ + }Out of curiousity, what the
private_datais for?Quoted 6 lines
When a probe is registered, it gives more flexibility to be able to pass a pointer to private data associated with that probe. For instance, if a tracer needs to register the same probe to many different tracepoints, but having a different context associated with each, it will pass the same function pointer with different
private_datato the registration function.
Quoted 6 lines
Hmm, only for tracepoint, it might be not so useful, because most of tracepoint's prototypes are different and so we can't use same probe to those tracepoints.
Anyway, it is useful for more general probe(ex. markers) if that is implemented on tracepoint ;-)
The usefulness of private_data in the tracepoints is indeed debatable, but given that we may have scenarios where code allocates its own data structure and has to pass it efficiently to the tracepoint callback, I think private_data can become quite useful at that point. It's useful whenever you have a tracer which can generate more than one trace, or collect more than one type of statistics depending on the user's needs.
Mathieu
Quoted 12 lines
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints
Hi Mathieu,
Quoted 16 lines · Mathieu Desnoyers
Quoted 15 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 14 lines · Mathieu Desnoyers
Quoted 6 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
We could, although markers, because they use var args, allow to put the iteration on the multi probe array out-of-line. Tracepoints cannot afford this and the iteration must be done at the initial call-site.
From what I see in your proposal, it's mostly to extract the
if()call()code from the inner__trace_mark()macro and to put it in a separate macro, am I correct ? This would make the macro more readable.
Quoted 6 lines
Quoted 2 lines
Sure, I think marker and tracepoint can share below functions;
- definition of static local variables in specific sectionsGiven that we could want to keep activation of tracepoints and markers separate (so they don't share the same namespace), declaring the static variables in separated sections seems to make sense to me.
Sorry, I'm not sure what is "separate activation".
As far as I can see, both tracepoints and markers are activated when its probe handlers are registered on each tracepoint/marker. Aren't it separated?
I did not mean integrating registering interfaces, but
I think that they can share base(internal) functions.
for example, both of them has XXX_update_range/_module_XXX_update etc.
IMHO, current code is not so good for maintenance. there are many code duplications (ex. kernel/module.c, I think that both of them (and imv too?) can share the code for handling its section and iterating entries). I'm not sure those duplications are acceptable.
Quoted 13 lines
Quoted 2 lines
- probe activation code (
if()call())
- multi probe handlingHrm, the thing here is that because markers allow to do the iteration on the multiple probe callbacks within an internal wrapper (instead of doing it on-site as in the tracepoints), it allows to do some further optimizations (less memory allocation and less pointer dereference in the single probe case, not having to prepare the
va_argsin theMARK_NOARGScase) which are only done because it does not have to add code to the instrumentation site. However, tracepoints cannot have such "generic" wrapper and we have to do the iteration on callbacks in the code added to the instrumented object. Therefore, I keep it as small as possible in terms of bytes of instructions.
OK, I see. So, __tracepoint_block() macro can specify handler function. what would you think about it?
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC PATCH] Kernel Tracepoints
Quoted 22 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
Quoted 19 lines · Mathieu Desnoyers
Quoted 17 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 7 lines · Mathieu Desnoyers
Quoted 6 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
Quoted 7 lines
We could, although markers, because they use var args, allow to put the iteration on the multi probe array out-of-line. Tracepoints cannot afford this and the iteration must be done at the initial call-site.
From what I see in your proposal, it's mostly to extract the
if()call()code from the inner__trace_mark()macro and to put it in a separate macro, am I correct ? This would make the macro more readable.Sure, I think marker and tracepoint can share below functions;
- definition of static local variables in specific sections
Quoted 9 lines
Quoted 3 lines
Given that we could want to keep activation of tracepoints and markers separate (so they don't share the same namespace), declaring the static variables in separated sections seems to make sense to me.
Sorry, I'm not sure what is "separate activation".
As far as I can see, both tracepoints and markers are activated when its probe handlers are registered on each tracepoint/marker. Aren't it separated?
Yes, it is separate. This is insured by the fact that markers and tracepoints are declared in different sections. Therefore, even if they have the same "name", they won't be used by each other.
Quoted 4 lines
I did not mean integrating registering interfaces, but
I think that they can share base(internal) functions.
for example, both of them has XXX_update_range/_module_XXX_update etc.
Hrm, but the sections and symbols on which these function iterate are different. I am unsure it's worth trying to merge such tiny functions.
Quoted 5 lines
IMHO, current code is not so good for maintenance. there are many code duplications (ex.
kernel/module.c, I think that both of them (and imv too?) can share the code for handling its section and iterating entries). I'm not sure those duplications are acceptable.
Given it's only slmost one-liners, and that there is some ordering to keep (markers and tracepoints must be updated before immediate values because they might influence the immediate value state), I don't think having a special section for these callbacks (a little bit like initcalls, but for module load) is a good option.
Quoted 15 lines
Quoted 4 lines
Quoted 3 lines
- probe activation code (
if()call())
- multi probe handlingQuoted 10 lines
Hrm, the thing here is that because markers allow to do the iteration on the multiple probe callbacks within an internal wrapper (instead of doing it on-site as in the tracepoints), it allows to do some further optimizations (less memory allocation and less pointer dereference in the single probe case, not having to prepare the
va_argsin theMARK_NOARGScase) which are only done because it does not have to add code to the instrumentation site. However, tracepoints cannot have such "generic" wrapper and we have to do the iteration on callbacks in the code added to the instrumented object. Therefore, I keep it as small as possible in terms of bytes of instructions.
Quoted 3 lines
OK, I see. So,
__tracepoint_block()macro can specify handler function. what would you think about it?
When I originally designed the markers, I tried to make sure there was absolutely no code duplication until I discovered that trying to read a huge amount of nested macros is just a pain starting from a certain level. If we only save a few duplicated lines but end up tying up markers and tracepoints, I am far from certain that it will make the code more readable.
I'll post a tracepoint version with the modifications you proposed (it's now placed earlier in the patchset), except the merge with markers.
Mathieu
Quoted 11 lines
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints
Hi Mathieu,
Quoted 31 lines · Mathieu Desnoyers
Quoted 21 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
Quoted 18 lines · Mathieu Desnoyers
Quoted 17 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 7 lines · Mathieu Desnoyers
Quoted 6 lines · * Masami Hiramatsu ([email protected]) wrote:
Quoted 2 lines
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
What would you think redesigning markers on tracepoints? because most of the logic (scaning sections, multiple probe and activation) seems very similar to markers.
Quoted 7 lines
We could, although markers, because they use var args, allow to put the iteration on the multi probe array out-of-line. Tracepoints cannot afford this and the iteration must be done at the initial call-site.
From what I see in your proposal, it's mostly to extract the
if()call()code from the inner__trace_mark()macro and to put it in a separate macro, am I correct ? This would make the macro more readable.Sure, I think marker and tracepoint can share below functions;
- definition of static local variables in specific sectionsQuoted 8 lines
Quoted 3 lines
Given that we could want to keep activation of tracepoints and markers separate (so they don't share the same namespace), declaring the static variables in separated sections seems to make sense to me.
Sorry, I'm not sure what is "separate activation".
As far as I can see, both tracepoints and markers are activated when its probe handlers are registered on each tracepoint/marker. Aren't it separated?
Quoted 3 lines
Yes, it is separate. This is insured by the fact that markers and tracepoints are declared in different sections. Therefore, even if they have the same "name", they won't be used by each other.
I reviewed both marker and tracepoint deeply in these days, and recognized what you said. Actually, markers and tracepoint would better have separate sections.
[...]
Quoted 16 lines
Quoted 12 lines
Quoted 12 lines
Quoted 2 lines
- probe activation code (
if()call())
- multi probe handlingHrm, the thing here is that because markers allow to do the iteration on the multiple probe callbacks within an internal wrapper (instead of doing it on-site as in the tracepoints), it allows to do some further optimizations (less memory allocation and less pointer dereference in the single probe case, not having to prepare the
va_argsin theMARK_NOARGScase) which are only done because it does not have to add code to the instrumentation site. However, tracepoints cannot have such "generic" wrapper and we have to do the iteration on callbacks in the code added to the instrumented object. Therefore, I keep it as small as possible in terms of bytes of instructions.Quoted 3 lines
OK, I see. So,
__tracepoint_block()macro can specify handler function. what would you think about it?
Quoted 6 lines
When I originally designed the markers, I tried to make sure there was absolutely no code duplication until I discovered that trying to read a huge amount of nested macros is just a pain starting from a certain level. If we only save a few duplicated lines but end up tying up markers and tracepoints, I am far from certain that it will make the code more readable.
After reviewing, I knew it is hard to implement markers on tracepoint. maybe, I need to find another way or maintenance both codes.
Quoted 2 lines
I'll post a tracepoint version with the modifications you proposed (it's now placed earlier in the patchset), except the merge with markers.
I see, if it is acceptable for upstream developers, I have no problem.
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC PATCH] Kernel Tracepoints (update)
In reply to Masami HiramatsuFollowing Masami's review....
Implementation of kernel tracepoints. Inspired from the Linux Kernel Markers.
Allows complete typing verification. No format string required.
TODO : Documentation/tracepoint.txt
Changelog :
- Use #name "_" #proto as string to identify the tracepoint in the tracepoint table. This will make sure not type mismatch happens due to connexion of a probe with the wrong type to a tracepoint declared with the same name in a different header.
--- include/asm-generic/vmlinux.lds.h | 4 include/linux/module.h | 17 + include/linux/tracepoint.h | 165 ++++++++++++ init/Kconfig | 7 kernel/Makefile | 1 kernel/module.c | 71 +++++ kernel/tracepoint.c | 495 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 759 insertions(+), 1 deletion(-)
init/Kconfig +7 -0
@@ -782,6 +782,13 @@ config PROFILING Say Y here to enable the extended profiling support mechanisms used by profilers such as OProfile. +config TRACEPOINTS + bool "Activate tracepoints" + default y + help + Place an empty function call at each tracepoint site. Can be + dynamically changed for a probe function. + config MARKERS bool "Activate markers" help
kernel/Makefile +1 -0
@@ -69,6 +69,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayac obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o obj-$(USE_IMMEDIATE) += immediate.o obj-$(CONFIG_MARKERS) += marker.o +obj-$(CONFIG_TRACEPOINTS) += tracepoint.o obj-$(CONFIG_LATENCYTOP) += latencytop.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
include/linux/tracepoint.h new file +165 -0
165 lines not on this page · raw message
include/asm-generic/vmlinux.lds.h +4 -0
@@ -53,6 +53,9 @@ VMLINUX_SYMBOL(__start___markers) = .; \ *(__markers ) \ VMLINUX_SYMBOL(__stop___markers) = .; \ + VMLINUX_SYMBOL(__start___tracepoints) = .; \ + *(__tracepoints ) \ + VMLINUX_SYMBOL(__stop___tracepoints) = .; \ VMLINUX_SYMBOL(__start___imv) = .; \ *(__imv )/* Immediate values: pointers */ \ VMLINUX_SYMBOL(__stop___imv) = .;
@@ -68,6 +71,7 @@ *(__imv_cond_end )/* Immediate condition end pointers */ \ VMLINUX_SYMBOL(__stop___imv_cond_end) = .; \ *(__markers_strings)/* Markers: strings */ \ + *(__tracepoints_strings)/* Tracepoints: strings */ \ } \ \ .rodata1 : AT(ADDR(.rodata1) - LOAD_OFFSET) { \
kernel/tracepoint.c new file +495 -0
495 lines not on this page · raw message
kernel/module.c +70 -1
108 lines not on this page · raw message
include/linux/module.h +17 -0
@@ -17,6 +17,7 @@#include <linux/moduleparam.h> #include <linux/immediate.h> #include <linux/marker.h> +#include <linux/tracepoint.h> #include <asm/local.h> #include <asm/module.h>
@@ -349,6 +350,10 @@ struct modulestruct marker *markers;unsigned int num_markers;#endif +#ifdef CONFIG_TRACEPOINTS +struct tracepoint *tracepoints; +unsigned int num_tracepoints; +#endif };#ifndef MODULE_ARCH_INIT #define MODULE_ARCH_INIT {}
@@ -459,6 +464,9 @@ extern void list_modules(void *call_dataextern void module_update_markers (void );extern int module_get_iter_markers (struct marker_iter *iter); +extern void module_update_tracepoints (void ); +extern int module_get_iter_tracepoints (struct tracepoint_iter *iter); +#else /* !CONFIG_MODULES... */ #define EXPORT_SYMBOL (sym)#define EXPORT_SYMBOL_GPL (sym)
@@ -568,6 +576,15 @@ static inline int module_get_iter_marker return 0; } +static inline void module_update_tracepoints (void ) +{ +} + +static inline int module_get_iter_tracepoints (struct tracepoint_iter *iter) +{ +return 0 ; +} +#endif /* CONFIG_MODULES */ #if defined(CONFIG_MODULES ) && defined(USE_IMMEDIATE )
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints (update)
Hi Mathieu,
I found a bug.
Mathieu Desnoyers wrote:
[...]
Quoted 12 lines
kernel/tracepoint.c new file +12
-0+/* +* Remove the tracepoint from the tracepoint hash table. Must be called with +* mutex_lock held. +*/ +static int remove_tracepoint (const char *name) +{ +struct hlist_head *head; +struct hlist_node *node; +struct tracepoint_entry *e; +int found =0 ; +size_t len =strlen (name) +1 ; +u32 hash =jhash (name, len-1 ,0 );
kernel/tracepoint.c line 245
Quoted 10 lines
kernel/tracepoint.c new file +10
-0+ + head = &tracepoint_table[hash & ((1 <<TRACEPOINT_HASH_BITS )-1 )]; +hlist_for_each_entry (e, node, head, hlist) { +if (!strcmp (name, e->name)) { + found =1 ; +break ; + } + } +if (!found) +return -ENOENT ;
before removing, you have to ensure refcount == 0. So,
if (e->refcount != 0) return -EBUSY;
kernel/tracepoint.c line 252
Quoted 7 lines
kernel/tracepoint.c new file +7
-0+hlist_del (&e->hlist); +/* Make sure the call_rcu has been executed */ +if (e->rcu_pending) +rcu_barrier (); +kfree (e); +return 0 ; +}
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Re: [RFC PATCH] Kernel Tracepoints (update)
Quoted 30 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
I found a bug.
Mathieu Desnoyers wrote:
[...]Quoted 12 lines
kernel/tracepoint.c new file +12
-0+/* +* Remove the tracepoint from the tracepoint hash table. Must be called with +* mutex_lock held. +*/ +static int remove_tracepoint (const char *name) +{ +struct hlist_head *head; +struct hlist_node *node; +struct tracepoint_entry *e; +int found =0 ; +size_t len =strlen (name) +1 ; +u32 hash =jhash (name, len-1 ,0 );kernel/tracepoint.c line 245
Quoted 10 lines
kernel/tracepoint.c new file +10
-0+ + head = &tracepoint_table[hash & ((1 <<TRACEPOINT_HASH_BITS )-1 )]; +hlist_for_each_entry (e, node, head, hlist) { +if (!strcmp (name, e->name)) { + found =1 ; +break ; + } + } +if (!found) +return -ENOENT ;before removing, you have to ensure refcount == 0. So,
Quoted 3 lines
if (e->refcount != 0) return -EBUSY;
Ah, right, I had
if (e->single.func != __mark_empty_function)
return -EBUSY;in the markers to test this and did not replace this test.
Thanks,
Mathieu
Quoted 19 lines
kernel/tracepoint.c line 252
Quoted 7 lines
kernel/tracepoint.c new file +7
-0+hlist_del (&e->hlist); +/* Make sure the call_rcu has been executed */ +if (e->rcu_pending) +rcu_barrier (); +kfree (e); +return 0 ; +}Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints (update)
In reply to Masami HiramatsuHi Masami,
I am thinking about removing the private_data, because such declaration won't work :
DEFINE_TRACE(kernel_irq_exit,
TPPROTO(void),
TPARGS());because the arguments become :
(void *private_data, void)
Any better idea ?
Mathieu
Quoted 52 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
I found a bug.
Mathieu Desnoyers wrote:
[...]Quoted 12 lines
kernel/tracepoint.c new file +12
-0+/* +* Remove the tracepoint from the tracepoint hash table. Must be called with +* mutex_lock held. +*/ +static int remove_tracepoint (const char *name) +{ +struct hlist_head *head; +struct hlist_node *node; +struct tracepoint_entry *e; +int found =0 ; +size_t len =strlen (name) +1 ; +u32 hash =jhash (name, len-1 ,0 );kernel/tracepoint.c line 245
Quoted 10 lines
kernel/tracepoint.c new file +10
-0+ + head = &tracepoint_table[hash & ((1 <<TRACEPOINT_HASH_BITS )-1 )]; +hlist_for_each_entry (e, node, head, hlist) { +if (!strcmp (name, e->name)) { + found =1 ; +break ; + } + } +if (!found) +return -ENOENT ;before removing, you have to ensure refcount == 0. So,
if (e->refcount != 0) return -EBUSY;kernel/tracepoint.c line 252
Quoted 7 lines
kernel/tracepoint.c new file +7
-0+hlist_del (&e->hlist); +/* Make sure the call_rcu has been executed */ +if (e->rcu_pending) +rcu_barrier (); +kfree (e); +return 0 ; +}Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC PATCH] Kernel Tracepoints (update)
Hi Mathieu,
Quoted 5 lines · Mathieu Desnoyers
Hi Masami,
I am thinking about removing the
private_data, because such declaration won't work :
Quoted 7 lines
DEFINE_TRACE(kernel_irq_exit,
TPPROTO(void), TPARGS());because the arguments become :
(void
*private_data, void)
Oh, you right.
since there is no tracepoint user who uses private_data, we can remove it.
Quoted 1 line
Any better idea ?
If you need it, I think you can introduce some macros like below.
#define TPPROTO(args...) (void *private_data, args)
#define __define_trace_register(name, proto) \ /*shared by DEFINE_TRACE/DEFINE_TRACE_NOARG*/
static inline int register_trace_##name(\
void (*probe)proto, \
void *private_data) \
{ \
return tracepoint_probe_register(#name ":" #proto, \
(void *)probe, private_data); \
} \
static inline void unregister_trace_##name( \
void (*probe)proto, \
void *private_data) \
{ \
tracepoint_probe_unregister(#name ":" #proto, \
(void *)probe, private_data); \
}#define DEFINE_TRACE_NOARG(name) \
static inline void _do_trace_##name(struct tracepoint *tp) \
...
static inline void trace_##name(void) \
...
__define_trace_register(name, (void *private_data))
But I think removing private_data is better...
Thank you,
Quoted 55 lines
Mathieu
Quoted 50 lines · * Masami Hiramatsu ([email protected]) wrote:
Hi Mathieu,
I found a bug.
Mathieu Desnoyers wrote:
[...]Quoted 12 lines
kernel/tracepoint.c new file +12
-0+/* +* Remove the tracepoint from the tracepoint hash table. Must be called with +* mutex_lock held. +*/ +static int remove_tracepoint (const char *name) +{ +struct hlist_head *head; +struct hlist_node *node; +struct tracepoint_entry *e; +int found =0 ; +size_t len =strlen (name) +1 ; +u32 hash =jhash (name, len-1 ,0 );kernel/tracepoint.c line 245
Quoted 10 lines
kernel/tracepoint.c new file +10
-0+ + head = &tracepoint_table[hash & ((1 <<TRACEPOINT_HASH_BITS )-1 )]; +hlist_for_each_entry (e, node, head, hlist) { +if (!strcmp (name, e->name)) { + found =1 ; +break ; + } + } +if (!found) +return -ENOENT ;before removing, you have to ensure refcount == 0. So,
if (e->refcount != 0) return -EBUSY;kernel/tracepoint.c line 252
Quoted 7 lines
kernel/tracepoint.c new file +7
-0+hlist_del (&e->hlist); +/* Make sure the call_rcu has been executed */ +if (e->rcu_pending) +rcu_barrier (); +kfree (e); +return 0 ; +}Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]
RFC PATCH 1/1 Tracepoint sched probes
In reply to Masami Hiramatsu** note : early RFC. This patch applies on a unreleased LTTng for 2.6.26-rc8 patchset.
Scheduler tracepoint probes
Only a single probe is implement as a POC.
--- init/Kconfig | 7 +++++++ kernel/Makefile | 1 + kernel/sched-trace.c | 28 ++++++++++++++++++++++++++++ kernel/sched-trace.h | 11 +++++++++++ kernel/sched.c | 5 +++-- 5 files changed, 50 insertions(+), 2 deletions(-)
kernel/sched-trace.c new file +28 -0
@@ -0,0 +1,28 @@ +#include <linux/module.h> +#include "sched-trace.h" + +static void probe_sched_switch (void *private_data,struct task_struct *prev, +struct task_struct *next) +{ +trace_mark (kernel_sched_schedule, +"prev_pid %d next_pid %d prev_state %ld" , + prev->pid, next->pid, prev->state); +} + +int __init sched_trace_init (void ) +{ +return register_trace_sched_switch (probe_sched_switch,NULL ); +} + +module_init (sched_trace_init); + +void __exit sched_trace_exit(void) +{ +unregister_trace_sched_switch (probe_sched_switch,NULL ); +} + +module_exit (sched_trace_exit); + +MODULE_LICENSE ("GPL" ); +MODULE_AUTHOR ("Mathieu Desnoyers" ); +MODULE_DESCRIPTION ("Scheduler Tracpoint Probes" );
kernel/sched-trace.h new file +11 -0
@@ -0,0 +1,11 @@ +#ifndef _KERNEL_SCHED_TRACE_H +#define _KERNEL_SCHED_TRACE_H + +#include <linux/sched.h> +#include <linux/tracepoint.h> + +DEFINE_TRACE (sched_switch, + TPPROTO(struct task_struct *prev, struct task_struct *next), +TPARGS (prev, next)); + +#endif
kernel/sched.c +3 -2
@@ -75,6 +75,8 @@#include <asm/tlb.h> #include <asm/irq_regs.h> +#include "sched-trace.h" +/* * Convert user-nice values [ -20 ... 0 ... 19 ] * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
@@ -2458,8 +2460,7 @@struct mm_struct *mm, *oldmm;prepare_task_switch (rq, prev, next); -trace_mark (internal_kernel_sched_schedule, -"prev %p next %p" , prev, next); +trace_sched_switch (prev, next); mm = next->mm; oldmm = prev->active_mm;/*
kernel/Makefile +1 -0
@@ -70,6 +70,7 @@ obj-$(USE_IMMEDIATE) += immediate.o obj-$(CONFIG_MARKERS) += marker.o obj-$(CONFIG_TRACEPOINTS) += tracepoint.o +obj-$(CONFIG_SCHED_TRACE) += sched-trace.o obj-$(CONFIG_LATENCYTOP) += latencytop.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
init/Kconfig +7 -0
@@ -789,6 +789,13 @@ Place an empty function call at each tracepoint site. Can be dynamically changed for a probe function. +config SCHED_TRACE + depends on TRACEPOINTS + tristate "Scheduler tracing" + default y + help + Build the scheduler tracing probes. + config MARKERS bool "Activate markers" help
Signature · 2 lines
Mathieu Desnoyers OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
Re: [RFC] Tracepoint proposal
In reply to Mathieu DesnoyersHi Mathieu,
Quoted 47 lines · Mathieu Desnoyers
Hi Peter,
I've tried to read through the comments recently posted to this thread (sorry I don't have time to answer them all specifically right now, a lot of this makes a lot of sense). I've tried to come up with a proposal, let's name it "tracepoint", which should hopefully address the full scope of the problem. Please tell me if it makes sense. It should allow compile-time verification of dynamically linked-in and activated tracepoints. I'll work on an implementation ASAP.
Mathieu
Tracepoint proposal
- Tracepoint infrastructure
- In-kernel users
- Complete typing, verified by the compiler
- Dynamically linked and activated- Marker infrastructure
- Exported API to userland
- Basic types only- Dynamic vs static
- In-kernel probes are dynamically linked, dynamically activated, connected to tracepoints. Type verification is done at compile-time. Those in-kernel probes can be a probe extracting the information to put in a marker or a specific in-kernel tracer such as ftrace.
- Information sinks (LTTng, SystemTAP) are dynamically connected to the markers inserted in the probes and are dynamically activated.- Near instrumentation site vs in a separate tracer module
A probe module, only if provided with the kernel tree, could connect to internal tracing sites. This argues for keeping the tracepoing probes near the instrumentation site code. However, if a tracer is general purpose and exports typing information to userspace through some mechanism, it should only export the "basic type" information and could be therefore shipped outside of the kernel tree.
In-kernel probes should be integrated to the kernel tree. They would be close to the instrumented kernel code and would translate between the in-kernel instrumentation and the "basic type" exports. Other in-kernel probes could provide a different output (statistics available through debugfs for instance). ftrace falls into this category.
Quoted 4 lines
Generic or specialized information "sinks" (LTTng, systemtap) could be connected to the markers put in tracepoint probes to extract the information to userspace. They would extract both typing information and the per-tracepoint execution information to userspace.
Your idea is good to me. I just worry about complexity. if both tracepoint and marker add information to other sections, both two functions cover each partially. Anyway, it depends on implementation.:-)
Quoted 35 lines
Therefore, the code would look like :
kernel/sched.c:#include "
sched-trace.h"
schedule()
{
...
trace_sched_switch(prev, next);
...
}
kernel/sched-trace.h:
DEFINE_TRACE(sched_switch, struct task_struct *prev, struct task_struct *next);
kernel/sched-trace.c:#include "
sched-trace.h"static probe_sched_switch(struct
task_struct*prev, structtask_struct
*next)
{
trace_mark(kernel_sched_switch, "prev_pid%dnext_pid%dprev_state%ld",prev->pid, next->pid, prev->state); }int
__initinit(void)
{
returnregister_sched_switch(probe_sched_switch);
}
Quoted 8 lines
void
__exitexit(void)
{
unregister_sched_switch(probe_sched_switch);
}Where
DEFINE_TRACEinternals declare a structure, a trace_* inline function, a register_trace_* and unregister_trace_* inline functions :
Hmm, if so, DEFINE_TRACE() still needs next and prev.:-)
Thank you,
Signature · 7 lines
Masami Hiramatsu Software Engineer Hitachi Computer Products (America) Inc. Software Solutions Division e-mail: [email protected]