Documentation and rcutorture changes for 3.9
Subsystems (5)
cover Documentation and rcutorture changes for 3.9
Hello!
The following are changes to documentation and rcutorture:
1. Export trace_clock_local() in order to allow rcutorture event
tracing to emit the time of the beginning of the RCU read-side critical section at the point where a failure is detected.
2. Reduce rcutorture's read-side tracing to include only failures,
thus cutting the number of events down to something reasonable (normally zero, in fact!).
3. Add atomic_xchg() to the list of atomic operations and memory
barriers, courtesy of Richard Braun.
Thanx, Paul
Documentation/atomic_ops.txt | 2 ++ Documentation/memory-barriers.txt | 1 + include/linux/rcupdate.h | 13 ++++++++++--- include/trace/events/rcu.h | 19 ++++++++++++++----- kernel/rcupdate.c | 9 ++++++--- kernel/rcutorture.c | 31 ++++++++++++++++++++++++------- kernel/trace/trace_clock.c | 1 + 7 files changed, 58 insertions(+), 18 deletions(-)
PATCH 3/3 Documentation: Memory barrier semantics of atomic_xchg()
In reply to Paul E. McKenneyFrom: Richard Braun <[email protected]>
Add atomic_xchg() to documentation for atomic operations and memory barriers.
--- Documentation/atomic_ops.txt | 2 ++ Documentation/memory-barriers.txt | 1 + 2 files changed, 3 insertions(+), 0 deletions(-)
Documentation/atomic_ops.txt +2 -0
@@ -253,6 +253,8 @@ This performs an atomic exchange operation on the atomic variable v, setting the given new value. It returns the old value that the atomic variable v had just before the operation. +atomic_xchg requires explicit memory barriers around the operation. + int atomic_cmpxchg(atomic_t *v, int old, int new); This performs an atomic compare exchange operation on the atomic value v,
Documentation/memory-barriers.txt +1 -0
@@ -1685,6 +1685,7 @@ explicit lock operations, described later). These include: xchg(); cmpxchg(); + atomic_xchg(); atomic_cmpxchg(); atomic_inc_return(); atomic_dec_return();
Signature · 1 line
1.7.8
PATCH 2/3 rcu: Reduce rcutorture tracing
In reply to Paul E. McKenneyFrom: "Paul E. McKenney" <[email protected]>
Currently, rcutorture traces every read-side access. This can be problematic because even a two-minute rcutorture run on a two-CPU system can generate 28,853,363 reads. Normally, only a failing read is of interest, so this commit traces adjusts rcutorture's tracing to only trace failing reads. The resulting event tracing records the time and the ->completed value captured at the beginning of the RCU read-side critical section, allowing correlation with other event-tracing messages.
--- include/linux/rcupdate.h | 13 ++++++++++--- include/trace/events/rcu.h | 19 ++++++++++++++----- kernel/rcupdate.c | 9 ++++++--- kernel/rcutorture.c | 31 ++++++++++++++++++++++++------- 4 files changed, 54 insertions(+), 18 deletions(-)
include/linux/rcupdate.h +10 -3
@@ -53,7 +53,10 @@ extern int rcutorture_runnable; /* for sysctl */extern void rcutorture_record_test_transition (void );extern void rcutorture_record_progress (unsigned long vernum);extern void do_trace_rcu_torture_read (char *rcutorturename, -struct rcu_head *rhp); +struct rcu_head *rhp, +unsigned long secs, +unsigned long c_old, +unsigned long c);#else static inline void rcutorture_record_test_transition (void ) {
@@ -63,9 +66,13 @@ static inline void rcutorture_record_progress(unsigned long vernum) }#ifdef CONFIG_RCU_TRACE extern void do_trace_rcu_torture_read (char *rcutorturename, -struct rcu_head *rhp); +struct rcu_head *rhp, +unsigned long secs, +unsigned long c_old, +unsigned long c);#else -#define do_trace_rcu_torture_read (rcutorturename, rhp) do { } while (0) +#define do_trace_rcu_torture_read (rcutorturename, rhp, secs, c_old, c) \ + do { } while (0)#endif #endif
include/trace/events/rcu.h +14 -5
@@ -523,22 +523,30 @@ TRACE_EVENT(rcu_batch_end,*/ TRACE_EVENT (rcu_torture_read, - TP_PROTO(char *rcutorturename, struct rcu_head *rhp), + TP_PROTO(char *rcutorturename, struct rcu_head *rhp, + unsigned long secs, unsigned long c_old, unsigned long c), -TP_ARGS (rcutorturename, rhp), +TP_ARGS (rcutorturename, rhp, secs, c_old, c),TP_STRUCT__entry ( __field(char *, rcutorturename) __field(struct rcu_head *, rhp) + __field(unsigned long, secs) + __field(unsigned long, c_old) + __field(unsigned long, c) ),TP_fast_assign ( __entry->rcutorturename = rcutorturename; __entry->rhp = rhp; + __entry->secs = secs; + __entry->c_old = c_old; + __entry->c = c; ), -TP_printk ("%s torture read %p" , - __entry->rcutorturename, __entry->rhp) +TP_printk ("%s torture read %p %luus c: %lu %lu" , + __entry->rcutorturename, __entry->rhp, + __entry->secs, __entry->c_old, __entry->c) );/*
@@ -608,7 +616,8 @@ TRACE_EVENT(rcu_barrier,#define trace_rcu_invoke_kfree_callback (rcuname, rhp, offset) do { } while (0)#define trace_rcu_batch_end (rcuname, callbacks_invoked, cb, nr, iit, risk) \ do { } while (0) -#define trace_rcu_torture_read (rcutorturename, rhp) do { } while (0) +#define trace_rcu_torture_read (rcutorturename, rhp, secs, c_old, c) \ + do { } while (0)#define trace_rcu_barrier (name, s, cpu, cnt, done) do { } while (0)#endif /* #else #ifdef CONFIG_RCU_TRACE */
kernel/rcupdate.c +6 -3
@@ -404,11 +404,14 @@ EXPORT_SYMBOL_GPL(rcuhead_debug_descr);#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ #if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) || defined(CONFIG_RCU_TRACE ) -void do_trace_rcu_torture_read (char *rcutorturename,struct rcu_head *rhp) +void do_trace_rcu_torture_read (char *rcutorturename,struct rcu_head *rhp, +unsigned long secs, +unsigned long c_old,unsigned long c) { -trace_rcu_torture_read (rcutorturename, rhp); +trace_rcu_torture_read (rcutorturename, rhp, secs, c_old, c); }EXPORT_SYMBOL_GPL (do_trace_rcu_torture_read);#else -#define do_trace_rcu_torture_read (rcutorturename, rhp) do { } while (0) +#define do_trace_rcu_torture_read (rcutorturename, rhp, secs, c_old, c) \ + do { } while (0)#endif
kernel/rcutorture.c +24 -7
@@ -46,6 +46,7 @@#include <linux/stat.h> #include <linux/srcu.h> #include <linux/slab.h> +#include <linux/trace_clock.h> #include <asm/byteorder.h> MODULE_LICENSE ("GPL" );
@@ -1028,7 +1029,6 @@ void rcutorture_trace_dump(void)return ;if (atomic_xchg (&beenhere,1 ) !=0 )return ; -do_trace_rcu_torture_read (cur_ops->name, (struct rcu_head *)~0UL );ftrace_dump (DUMP_ALL ); }
@@ -1042,13 +1042,16 @@ static void rcu_torture_timer(unsigned long unused) {int idx;int completed; +int completed_end;static DEFINE_RCU_RANDOM (rand);static DEFINE_SPINLOCK (rand_lock);struct rcu_torture *p;int pipe_count; +unsigned long long ts; idx = cur_ops->readlock (); completed = cur_ops->completed (); + ts =trace_clock_local (); p = rcu_dereference_check(rcu_torture_current, rcu_read_lock_bh_held() || rcu_read_lock_sched_held() ||
@@ -1058,7 +1061,6 @@ static void rcu_torture_timer(unsigned long unused) cur_ops->readunlock (idx);return ; } -do_trace_rcu_torture_read (cur_ops->name, &p->rtort_rcu);if (p->rtort_mbtest ==0 )atomic_inc (&n_rcu_torture_mberror);spin_lock (&rand_lock);
@@ -1071,10 +1073,16 @@ static void rcu_torture_timer(unsigned long unused)/* Should not happen, but... */ pipe_count =RCU_TORTURE_PIPE_LEN ; } -if (pipe_count >1 ) + completed_end = cur_ops->completed (); +if (pipe_count >1 ) { +unsigned long __maybe_unused ts_rem =do_div (ts,NSEC_PER_USEC ); + +do_trace_rcu_torture_read (cur_ops->name, &p->rtort_rcu, ts, + completed, completed_end);rcutorture_trace_dump (); + }__this_cpu_inc (rcu_torture_count[pipe_count]); - completed = cur_ops->completed () - completed; + completed = completed_end - completed;if (completed >RCU_TORTURE_PIPE_LEN ) {/* Should not happen, but... */ completed =RCU_TORTURE_PIPE_LEN ;
@@ -1094,11 +1102,13 @@ static int rcu_torture_reader(void *arg) {int completed; +int completed_end;int idx;DEFINE_RCU_RANDOM (rand);struct rcu_torture *p;int pipe_count;struct timer_list t; +unsigned long long ts;VERBOSE_PRINTK_STRING ("rcu_torture_reader task started" );set_user_nice (current,19 );
@@ -1112,6 +1122,7 @@ rcu_torture_reader(void *arg) } idx = cur_ops->readlock (); completed = cur_ops->completed (); + ts =trace_clock_local (); p = rcu_dereference_check(rcu_torture_current, rcu_read_lock_bh_held() || rcu_read_lock_sched_held() ||
@@ -1122,7 +1133,6 @@ rcu_torture_reader(void *arg)schedule_timeout_interruptible (HZ );continue ; } -do_trace_rcu_torture_read (cur_ops->name, &p->rtort_rcu);if (p->rtort_mbtest ==0 )atomic_inc (&n_rcu_torture_mberror); cur_ops->read_delay (&rand);
@@ -1132,10 +1142,17 @@ rcu_torture_reader(void *arg)/* Should not happen, but... */ pipe_count =RCU_TORTURE_PIPE_LEN ; } -if (pipe_count >1 ) + completed_end = cur_ops->completed (); +if (pipe_count >1 ) { +unsigned long __maybe_unused ts_rem = +do_div (ts,NSEC_PER_USEC ); + +do_trace_rcu_torture_read (cur_ops->name, &p->rtort_rcu, + ts, completed, completed_end);rcutorture_trace_dump (); + }__this_cpu_inc (rcu_torture_count[pipe_count]); - completed = cur_ops->completed () - completed; + completed = completed_end - completed;if (completed >RCU_TORTURE_PIPE_LEN ) {/* Should not happen, but... */ completed =RCU_TORTURE_PIPE_LEN ;
Signature · 1 line
1.7.8
PATCH 1/3 tracing: Export trace_clock_local()
In reply to Paul E. McKenneyFrom: "Paul E. McKenney" <[email protected]>
The rcutorture tests need to be able to trace the time of the beginning of an RCU read-side critical section, and thus need access to trace_clock_local(). This commit therefore adds a the needed EXPORT_SYMBOL_GPL().
--- kernel/trace/trace_clock.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
kernel/trace/trace_clock.c +1 -0
@@ -44,6 +44,7 @@ u64 notrace trace_clock_local(void)return clock; } +EXPORT_SYMBOL_GPL (trace_clock_local);/* * trace_clock(): 'between' trace clock. Not completely serialized,
Signature · 1 line
1.7.8
Quoted 4 lines · Paul E. McKenney
Hello!
The following are changes to documentation and rcutorture:
Quoted 8 lines
1. Export
trace_clock_local()in order to allow rcutorture event
tracing to emit the time of the beginning of the RCU read-side critical section at the point where a failure is detected.
2. Reduce rcutorture's read-side tracing to include only failures,
thus cutting the number of events down to something reasonable (normally zero, in fact!).
3. Addatomic_xchg()to the list of atomic operations and memory
barriers, courtesy of Richard Braun.
For the whole series: