summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2011-06-17 15:53:19 -0700
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2011-09-28 21:38:12 -0700
commit29c00b4a1d9e277786120032aa8364631820d863 (patch)
tree23bf0c8cdb5268ef92ef9ed007639705e922b1b0 /include
parent9d68197c05201d8edc70d58bd1d5dad05d8455e8 (diff)
downloadlinux-29c00b4a1d9e277786120032aa8364631820d863.tar.gz
linux-29c00b4a1d9e277786120032aa8364631820d863.tar.bz2
linux-29c00b4a1d9e277786120032aa8364631820d863.zip
rcu: Add event-tracing for RCU callback invocation
There was recently some controversy about the overhead of invoking RCU callbacks. Add TRACE_EVENT()s to obtain fine-grained timings for the start and stop of a batch of callbacks and also for each callback invoked. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/rcupdate.h50
-rw-r--r--include/trace/events/rcu.h98
2 files changed, 98 insertions, 50 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index ae5327de41aa..dd2bc2c6a285 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -794,44 +794,6 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
#define RCU_INIT_POINTER(p, v) \
p = (typeof(*v) __force __rcu *)(v)
-/*
- * debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally
- * by call_rcu() and rcu callback execution, and are therefore not part of the
- * RCU API. Leaving in rcupdate.h because they are used by all RCU flavors.
- */
-
-#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD
-# define STATE_RCU_HEAD_READY 0
-# define STATE_RCU_HEAD_QUEUED 1
-
-extern struct debug_obj_descr rcuhead_debug_descr;
-
-static inline void debug_rcu_head_queue(struct rcu_head *head)
-{
- WARN_ON_ONCE((unsigned long)head & 0x3);
- debug_object_activate(head, &rcuhead_debug_descr);
- debug_object_active_state(head, &rcuhead_debug_descr,
- STATE_RCU_HEAD_READY,
- STATE_RCU_HEAD_QUEUED);
-}
-
-static inline void debug_rcu_head_unqueue(struct rcu_head *head)
-{
- debug_object_active_state(head, &rcuhead_debug_descr,
- STATE_RCU_HEAD_QUEUED,
- STATE_RCU_HEAD_READY);
- debug_object_deactivate(head, &rcuhead_debug_descr);
-}
-#else /* !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
-static inline void debug_rcu_head_queue(struct rcu_head *head)
-{
-}
-
-static inline void debug_rcu_head_unqueue(struct rcu_head *head)
-{
-}
-#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
-
static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
{
return offset < 4096;
@@ -850,18 +812,6 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
call_rcu(head, (rcu_callback)offset);
}
-extern void kfree(const void *);
-
-static inline void __rcu_reclaim(struct rcu_head *head)
-{
- unsigned long offset = (unsigned long)head->func;
-
- if (__is_kfree_rcu_offset(offset))
- kfree((void *)head - offset);
- else
- head->func(head);
-}
-
/**
* kfree_rcu() - kfree an object after a grace period.
* @ptr: pointer to kfree
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
new file mode 100644
index 000000000000..db3f6e9e63e6
--- /dev/null
+++ b/include/trace/events/rcu.h
@@ -0,0 +1,98 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM rcu
+
+#if !defined(_TRACE_RCU_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_RCU_H
+
+#include <linux/tracepoint.h>
+
+/*
+ * Tracepoint for calling rcu_do_batch, performed to start callback invocation:
+ */
+TRACE_EVENT(rcu_batch_start,
+
+ TP_PROTO(long callbacks_ready, int blimit),
+
+ TP_ARGS(callbacks_ready, blimit),
+
+ TP_STRUCT__entry(
+ __field( long, callbacks_ready )
+ __field( int, blimit )
+ ),
+
+ TP_fast_assign(
+ __entry->callbacks_ready = callbacks_ready;
+ __entry->blimit = blimit;
+ ),
+
+ TP_printk("CBs=%ld bl=%d", __entry->callbacks_ready, __entry->blimit)
+);
+
+/*
+ * Tracepoint for the invocation of a single RCU callback
+ */
+TRACE_EVENT(rcu_invoke_callback,
+
+ TP_PROTO(struct rcu_head *rhp),
+
+ TP_ARGS(rhp),
+
+ TP_STRUCT__entry(
+ __field( void *, rhp )
+ __field( void *, func )
+ ),
+
+ TP_fast_assign(
+ __entry->rhp = rhp;
+ __entry->func = rhp->func;
+ ),
+
+ TP_printk("rhp=%p func=%pf", __entry->rhp, __entry->func)
+);
+
+/*
+ * Tracepoint for the invocation of a single RCU kfree callback
+ */
+TRACE_EVENT(rcu_invoke_kfree_callback,
+
+ TP_PROTO(struct rcu_head *rhp, unsigned long offset),
+
+ TP_ARGS(rhp, offset),
+
+ TP_STRUCT__entry(
+ __field(void *, rhp )
+ __field(unsigned long, offset )
+ ),
+
+ TP_fast_assign(
+ __entry->rhp = rhp;
+ __entry->offset = offset;
+ ),
+
+ TP_printk("rhp=%p func=%ld", __entry->rhp, __entry->offset)
+);
+
+/*
+ * Tracepoint for leaving rcu_do_batch, performed after callback invocation:
+ */
+TRACE_EVENT(rcu_batch_end,
+
+ TP_PROTO(int callbacks_invoked),
+
+ TP_ARGS(callbacks_invoked),
+
+ TP_STRUCT__entry(
+ __field( int, callbacks_invoked )
+ ),
+
+ TP_fast_assign(
+ __entry->callbacks_invoked = callbacks_invoked;
+ ),
+
+ TP_printk("CBs-invoked=%d", __entry->callbacks_invoked)
+);
+
+#endif /* _TRACE_RCU_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>