[PATCH][RFC] tracing/rcu: Add trace_##name##__rcuidle() static tracepoint for inside rcu_idle_exit() sections
Paul E. McKenney
paulmck at linux.vnet.ibm.com
Mon Feb 6 18:38:05 EST 2012
On Mon, Feb 06, 2012 at 04:18:33PM -0500, Steven Rostedt wrote:
> As I have said, I may find a better solution than to create a
> TRACE_EVENT_IDLE(), and I believe I have :-)
>
> A added a new static inline function that lets *any* tracepoint be used
> inside a rcu_idle_exit() section. And this also solves the problem where
> the same tracepoint may be used inside a rcu_idle_exit() section as well
> as outside of one.
>
> I added a new tracepoint function with a "_rcuidle" extension. All
> tracepoints can be used with either the normal "trace_foobar()"
> function, or the "trace_foobar_rcuidle()" function when inside a
> rcu_idle_exit() section.
>
> Ideally, this patch would be broken up into two commits. The first would
> change the tracepoint.h to introduce the new trace_foobar_rcuidle()
> static inline, and the second patch would change the power tracepoints
> to use this tracepoint function. For the RFC, I'm keeping it as a single
> patch.
>
> Another nice aspect about this patch is that "static inline"s are not
> compiled into text when not used. So only the tracepoints that actually
> use the _rcuidle() version will have them defined in the actual text
> that is booted.
>
> -- Steve
Aside from the "pre;" below needing to precede rcu_read_lock_sched_notrace()
as Josh noted, this looks reasonable to me.
Thanx, Paul
> Signed-off-by: Steven Rostedt <rostedt at goodmis.org>
>
> Index: linux-trace.git/include/linux/tracepoint.h
> ===================================================================
> --- linux-trace.git.orig/include/linux/tracepoint.h
> +++ linux-trace.git/include/linux/tracepoint.h
> @@ -114,7 +114,7 @@ static inline void tracepoint_synchroniz
> * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
> * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
> */
> -#define __DO_TRACE(tp, proto, args, cond) \
> +#define __DO_TRACE(tp, proto, args, cond, pre, post) \
> do { \
> struct tracepoint_func *it_func_ptr; \
> void *it_func; \
> @@ -123,6 +123,7 @@ static inline void tracepoint_synchroniz
> if (!(cond)) \
> return; \
> rcu_read_lock_sched_notrace(); \
> + pre; \
> it_func_ptr = rcu_dereference_sched((tp)->funcs); \
> if (it_func_ptr) { \
> do { \
> @@ -132,6 +133,7 @@ static inline void tracepoint_synchroniz
> } while ((++it_func_ptr)->func); \
> } \
> rcu_read_unlock_sched_notrace(); \
> + post; \
> } while (0)
>
> /*
> @@ -139,7 +141,7 @@ static inline void tracepoint_synchroniz
> * not add unwanted padding between the beginning of the section and the
> * structure. Force alignment to the same alignment as the section start.
> */
> -#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
> +#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
> extern struct tracepoint __tracepoint_##name; \
> static inline void trace_##name(proto) \
> { \
> @@ -147,7 +149,17 @@ static inline void tracepoint_synchroniz
> __DO_TRACE(&__tracepoint_##name, \
> TP_PROTO(data_proto), \
> TP_ARGS(data_args), \
> - TP_CONDITION(cond)); \
> + TP_CONDITION(cond),,); \
> + } \
> + static inline void trace_##name##_rcuidle(proto) \
> + { \
> + if (static_branch(&__tracepoint_##name.key)) \
> + __DO_TRACE(&__tracepoint_##name, \
> + TP_PROTO(data_proto), \
> + TP_ARGS(data_args), \
> + TP_CONDITION(cond), \
> + rcu_idle_exit(), \
> + rcu_idle_enter()); \
> } \
> static inline int \
> register_trace_##name(void (*probe)(data_proto), void *data) \
> @@ -190,7 +202,7 @@ static inline void tracepoint_synchroniz
> EXPORT_SYMBOL(__tracepoint_##name)
>
> #else /* !CONFIG_TRACEPOINTS */
> -#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
> +#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
> static inline void trace_##name(proto) \
> { } \
> static inline int \
> Index: linux-trace.git/arch/x86/kernel/process.c
> ===================================================================
> --- linux-trace.git.orig/arch/x86/kernel/process.c
> +++ linux-trace.git/arch/x86/kernel/process.c
> @@ -377,8 +377,8 @@ static inline int hlt_use_halt(void)
> void default_idle(void)
> {
> if (hlt_use_halt()) {
> - trace_power_start(POWER_CSTATE, 1, smp_processor_id());
> - trace_cpu_idle(1, smp_processor_id());
> + trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id());
> + trace_cpu_idle_rcuidle(1, smp_processor_id());
> current_thread_info()->status &= ~TS_POLLING;
> /*
> * TS_POLLING-cleared state must be visible before we
> @@ -391,7 +391,7 @@ void default_idle(void)
> else
> local_irq_enable();
> current_thread_info()->status |= TS_POLLING;
> - trace_power_end(smp_processor_id());
> + trace_power_end_rcuidle(smp_processor_id());
> trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
> } else {
> local_irq_enable();
> @@ -450,8 +450,8 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
> static void mwait_idle(void)
> {
> if (!need_resched()) {
> - trace_power_start(POWER_CSTATE, 1, smp_processor_id());
> - trace_cpu_idle(1, smp_processor_id());
> + trace_power_start_rcuidle(POWER_CSTATE, 1, smp_processor_id());
> + trace_cpu_idle_rcuidle(1, smp_processor_id());
> if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
> clflush((void *)¤t_thread_info()->flags);
>
> @@ -461,8 +461,8 @@ static void mwait_idle(void)
> __sti_mwait(0, 0);
> else
> local_irq_enable();
> - trace_power_end(smp_processor_id());
> - trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
> + trace_power_end_rcuidle(smp_processor_id());
> + trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
> } else
> local_irq_enable();
> }
> @@ -474,13 +474,13 @@ static void mwait_idle(void)
> */
> static void poll_idle(void)
> {
> - trace_power_start(POWER_CSTATE, 0, smp_processor_id());
> - trace_cpu_idle(0, smp_processor_id());
> + trace_power_start_rcuidle(POWER_CSTATE, 0, smp_processor_id());
> + trace_cpu_idle_rcuidle(0, smp_processor_id());
> local_irq_enable();
> while (!need_resched())
> cpu_relax();
> - trace_power_end(smp_processor_id());
> - trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
> + trace_power_end_rcuidle(smp_processor_id());
> + trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
> }
>
> /*
>
>
More information about the linux-arm-kernel
mailing list