All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frederic Weisbecker <fweisbec@gmail.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: linux-kernel@vger.kernel.org, Ingo Molnar <mingo@elte.hu>,
	Andrew Morton <akpm@linux-foundation.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Peter Zijlstra <peterz@infradead.org>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Mathieu Desnoyers <compudj@krystal.dyndns.org>,
	Lai Jiangshan <laijs@cn.fujitsu.com>,
	Li Zefan <lizf@cn.fujitsu.com>,
	Masami Hiramatsu <mhiramat@redhat.com>,
	Christoph Hellwig <hch@lst.de>,
	Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Subject: Re: [PATCH 2/9 - v2][RFC] tracing: Let tracepoints have data passed to tracepoint callbacks
Date: Fri, 7 May 2010 05:52:32 +0200	[thread overview]
Message-ID: <20100507035230.GB8069@nowhere> (raw)
In-Reply-To: <20100504034201.896240097@goodmis.org>

On Mon, May 03, 2010 at 11:40:47PM -0400, Steven Rostedt wrote:
> From: Steven Rostedt <srostedt@redhat.com>
> 
> This patch allows data to be passed to the tracepoint callbacks
> if the tracepoint was created to do so.
> 
> The DECLARE_TRACE() now adds two new functions:
> 
> 	register_trace_mytracepoint_data()
> 	unregister_trace_mytracepoint_data()
> 
> These two are the same as the original
> 
> 	register_trace_mytracepoint()
> 	unregister_trace_mytracepoint()
> 
> But now allow you to pass a private data pointer that will
> be passed to the callback handle. For example:
> 
> DECLARE_TRACE(mytracepoint, int value, value);
> 
> will create a function called trace_mytracepoint()
> 
> 	void trace_mytracepoint(int value);
> 
> If the user wants to pass data to register a function to this tracepoint
> and have data also passed to this callback, they can use:
> 
> 	int mycallback(int value, void *data);
> 
> 	register_trace_mytracepoint_data(mycallback, mydata);
> 
> Then the mycallback() will receive the "mydata" as the parameter after
> the args.
> 
> A more detailed example:
> 
>   DECLARE_TRACE(mytracepoint, TP_PROTO(int status), TP_ARGS(status));
> 
>   /* In the C file */
> 
>   DEFINE_TRACE(mytracepoint, TP_PROTO(int status), TP_ARGS(status));
> 
>   [...]
> 
>        trace_mytacepoint(status);
> 
>   /* In a file registering this tracepoint */
> 
>   int my_callback(int status, void *data)
>   {
> 	struct my_struct my_data = data;
> 	[...]
>   }
> 
>   [...]
> 	my_data = kmalloc(sizeof(*my_data), GFP_KERNEL);
> 	init_my_data(my_data);
> 	register_trace_mytracepoint_data(my_callback, my_data);
> 
> The same callback can also be registered to the same tracepoint as long
> as the data registered is the different. Note, the data must also be used
> to unregister the callback:
> 
> 	unregister_trace_mytracepoint_data(my_callback, my_data);
> 
> Because of the data parameter, tracepoints declared this way can not have
> no args. That is:
> 
>   DECLARE_TRACE(mytracepoint, TP_PROTO(void), TP_ARGS());
> 
> will cause an error.
> 
> If no arguments are needed, a new macro can be used instead:
> 
>   DECLARE_TRACE_NOARGS(mytracepoint);
> 
> Since there are no arguments, the proto and args fields are left out.
> 
> This is part of a series to make the tracepoint footprint smaller:
> 
>    text	   data	    bss	    dec	    hex	filename
> 5788186	1337252	9351592	16477030	 fb6b66	vmlinux.orig
> 5792282	1333796	9351592	16477670	 fb6de6	vmlinux.class
> 5793448	1333780	9351592	16478820	 fb7264	vmlinux.tracepoint
> 
> Again, this patch also increases the size of the kernel, but
> lays the ground work for decreasing it.
> 
>  v2: Made the DECLARE_TRACE() have the ability to pass arguments
>      and added a new DECLARE_TRACE_NOARGS() for tracepoints that
>      do not need any arguments.
> 
> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> ---
>  include/linux/tracepoint.h             |   94 +++++++++++++++++++++++++-------
>  kernel/tracepoint.c                    |   91 +++++++++++++++++--------------
>  samples/tracepoints/tp-samples-trace.h |    4 +-
>  3 files changed, 126 insertions(+), 63 deletions(-)
> 
> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
> index 78b4bd3..ee8059a 100644
> --- a/include/linux/tracepoint.h
> +++ b/include/linux/tracepoint.h
> @@ -20,12 +20,17 @@
>  struct module;
>  struct tracepoint;
>  
> +struct tracepoint_func {
> +	void *func;
> +	void *data;
> +};
> +
>  struct tracepoint {
>  	const char *name;		/* Tracepoint name */
>  	int state;			/* State. */
>  	void (*regfunc)(void);
>  	void (*unregfunc)(void);
> -	void **funcs;
> +	struct tracepoint_func *funcs;
>  } __attribute__((aligned(32)));		/*
>  					 * Aligned on 32 bytes because it is
>  					 * globally visible and gcc happily
> @@ -46,14 +51,18 @@ struct tracepoint {
>   */
>  #define __DO_TRACE(tp, proto, args)					\
>  	do {								\
> -		void **it_func;						\
> +		struct tracepoint_func *it_func_ptr;			\
> +		void *it_func;						\
> +		void *__data;						\
>  									\
>  		rcu_read_lock_sched_notrace();				\
> -		it_func = rcu_dereference_sched((tp)->funcs);		\
> -		if (it_func) {						\
> +		it_func_ptr = rcu_dereference_sched((tp)->funcs);	\
> +		if (it_func_ptr) {					\
>  			do {						\
> -				((void(*)(proto))(*it_func))(args);	\
> -			} while (*(++it_func));				\
> +				it_func = (it_func_ptr)->func;		\
> +				__data = (it_func_ptr)->data;		\
> +				((void(*)(proto))(it_func))(args);	\


So, we had a talk about this and we concluded that it is probably fine
on every archs to push one more argument than needed in a function.

But I think it would be nice to add a comment about this. Firstly
because this line breaks all the self-explanation of the code, I mean
I tried hard to find how the non-data callback case was handled :)
Secondly to also to avoid people asking what happens here.




> +			} while ((++it_func_ptr)->func);		\
>  		}							\
>  		rcu_read_unlock_sched_notrace();			\
>  	} while (0)
> @@ -63,23 +72,47 @@ struct tracepoint {
>   * 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)				\
> +#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
>  	extern struct tracepoint __tracepoint_##name;			\
>  	static inline void trace_##name(proto)				\
>  	{								\
>  		if (unlikely(__tracepoint_##name.state))		\
>  			__DO_TRACE(&__tracepoint_##name,		\
> -				TP_PROTO(proto), TP_ARGS(args));	\
> +				TP_PROTO(data_proto),			\
> +				TP_ARGS(data_args));			\
>  	}								\
>  	static inline int register_trace_##name(void (*probe)(proto))	\
>  	{								\
> -		return tracepoint_probe_register(#name, (void *)probe);	\
> +		return tracepoint_probe_register(#name, (void *)probe,	\
> +						 NULL);			\
> +	}								\
> +	static inline int unregister_trace_##name(void (*probe)(proto)) \
> +	{								\
> +		return tracepoint_probe_unregister(#name, (void *)probe,\
> +						   NULL);		\
>  	}								\
> -	static inline int unregister_trace_##name(void (*probe)(proto))	\
> +	static inline int						\
> +	register_trace_##name##_data(void (*probe)(data_proto),		\
> +				     void *data)			\
>  	{								\
> -		return tracepoint_probe_unregister(#name, (void *)probe);\
> +		return tracepoint_probe_register(#name, (void *)probe,	\
> +						 data);			\
> +	}								\
> +	static inline int						\
> +	unregister_trace_##name##_data(void (*probe)(data_proto),	\
> +				       void *data)			\
> +	{								\
> +		return tracepoint_probe_unregister(#name, (void *)probe,\
> +						   data);		\
>  	}
>  
> +#define DECLARE_TRACE_NOARGS(name)					\
> +		__DECLARE_TRACE(name, void, , void *__data, __data)



That too, may be, deserves a small comment :)



> +
> +#define DECLARE_TRACE(name, proto, args)				\
> +		__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),	\
> +				PARAMS(proto, void *__data),		\
> +				PARAMS(args, __data))
>  
>  #define DEFINE_TRACE_FN(name, reg, unreg)				\
>  	static const char __tpstrtab_##name[]				\
> @@ -100,19 +133,37 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin,
>  	struct tracepoint *end);
>  
>  #else /* !CONFIG_TRACEPOINTS */
> -#define DECLARE_TRACE(name, proto, args)				\
> -	static inline void _do_trace_##name(struct tracepoint *tp, proto) \
> -	{ }								\
> +#define __DECLARE_TRACE(name, proto, args, data_proto, data_args)	\
>  	static inline void trace_##name(proto)				\
> -	{ }								\
> +	{								\
> +	}								\
>  	static inline int register_trace_##name(void (*probe)(proto))	\
>  	{								\
>  		return -ENOSYS;						\
>  	}								\
> -	static inline int unregister_trace_##name(void (*probe)(proto))	\
> +	static inline int unregister_trace_##name(void (*probe)(proto)) \
> +	{								\
> +		return -ENOSYS;						\
> +	}								\
> +	static inline int						\
> +	register_trace_##name##_data(void (*probe)(data_proto),		\
> +				     void *data)			\
> +	{								\
> +		return -ENOSYS;						\
> +	}								\
> +	static inline int						\
> +	unregister_trace_##name##_data(void (*probe)(data_proto),	\
> +				       void *data)			\
>  	{								\
>  		return -ENOSYS;						\
>  	}
> +#define DECLARE_TRACE_NOARGS(name)					\
> +		__DECLARE_TRACE(name, void, , void *__data, __data)
> +
> +#define DECLARE_TRACE(name, proto, args)				\
> +		__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),	\
> +				PARAMS(proto, void *__data),		\
> +				PARAMS(args, __data))




It seems that the on and off cases are exactly the same for DECLARE_TRACE*(),
you could provide a single version and let the __DECLARE_TRACE() do
the on/off trick.

Thanks.


  reply	other threads:[~2010-05-07  3:52 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-04  3:40 [PATCH 0/9 - v2][RFC] tracing: Lowering the footprint of TRACE_EVENTs Steven Rostedt
2010-05-04  3:40 ` [PATCH 1/9 - v2][RFC] tracing: Create class struct for events Steven Rostedt
2010-05-07  4:21   ` Frederic Weisbecker
2010-05-04  3:40 ` [PATCH 2/9 - v2][RFC] tracing: Let tracepoints have data passed to tracepoint callbacks Steven Rostedt
2010-05-07  3:52   ` Frederic Weisbecker [this message]
2010-05-07 14:09     ` Steven Rostedt
2010-05-07 18:06       ` Frederic Weisbecker
2010-05-07 19:10         ` Steven Rostedt
2010-05-04  3:40 ` [PATCH 3/9 - v2][RFC] tracing: Remove per event trace registering Steven Rostedt
2010-05-07  4:20   ` Frederic Weisbecker
2010-05-07 12:42     ` Steven Rostedt
2010-05-07 14:54     ` Mathieu Desnoyers
2010-05-07 15:12       ` Steven Rostedt
2010-05-07 15:31         ` Mathieu Desnoyers
2010-05-07 15:43           ` Steven Rostedt
2010-05-07 18:01       ` Frederic Weisbecker
2010-05-07 19:08         ` Steven Rostedt
2010-05-07 20:03           ` Frederic Weisbecker
2010-05-07 20:58           ` Mathieu Desnoyers
2010-05-07  8:20   ` Li Zefan
2010-05-07 12:59     ` Steven Rostedt
2010-05-04  3:40 ` [PATCH 4/9 - v2][RFC] tracing: Move fields from event to class structure Steven Rostedt
2010-05-07  4:49   ` Frederic Weisbecker
2010-05-07 12:57     ` Steven Rostedt
2010-05-04  3:40 ` [PATCH 5/9 - v2][RFC] tracing: Move raw_init from events to class Steven Rostedt
2010-05-04  3:40 ` [PATCH 6/9 - v2][RFC] tracing: Allow events to share their print functions Steven Rostedt
2010-05-04  3:40 ` [PATCH 7/9 - v2][RFC] tracing: Move print functions into event class Steven Rostedt
2010-05-04  3:40 ` [PATCH 8/9 - v2][RFC] tracing: Remove duplicate id information in event structure Steven Rostedt
2010-05-04  3:40 ` [PATCH 9/9 - v2][RFC] tracing: Combine event filter_active and enable into single flags field Steven Rostedt
  -- strict thread matches above, loose matches on Subject: below --
2010-05-07 12:40 [PATCH 2/9 - v2][RFC] tracing: Let tracepoints have data passed to tracepoint callbacks Steven Rostedt
2010-05-07 14:39 ` [PATCH 2/9 - v2][RFC] tracing: Let tracepoints have data?passed " Mathieu Desnoyers
2010-05-07 14:55   ` Steven Rostedt
2010-05-07 15:08     ` Mathieu Desnoyers
2010-05-07 15:15       ` Steven Rostedt
2010-05-07 15:30         ` Mathieu Desnoyers
2010-05-07 15:45           ` Steven Rostedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100507035230.GB8069@nowhere \
    --to=fweisbec@gmail.com \
    --cc=acme@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=compudj@krystal.dyndns.org \
    --cc=hch@lst.de \
    --cc=laijs@cn.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizf@cn.fujitsu.com \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mhiramat@redhat.com \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.