This patch consolidates the RCU tracing code in the preemptible
RCU implementation, moves them to a separate "trace" file and
cleans up the #ifdefs. Moving to a separate file will eventually
allow dynamic tracing of RCU implementation.

Signed-off-by: Paul McKenney <[EMAIL PROTECTED]>
Signed-off-by: Dipankar Sarma <[EMAIL PROTECTED]>
---



diff -puN include/linux/rcupreempt.h~rcu-preempt-trace 
include/linux/rcupreempt.h
--- linux-2.6.20-rc3-mm1-rcu/include/linux/rcupreempt.h~rcu-preempt-trace       
2007-01-15 15:36:56.000000000 +0530
+++ linux-2.6.20-rc3-mm1-rcu-dipankar/include/linux/rcupreempt.h        
2007-01-15 15:36:56.000000000 +0530
@@ -61,5 +61,15 @@ extern void __rcu_init(void);
 extern void rcu_check_callbacks(int cpu, int user);
 extern void rcu_restart_cpu(int cpu);
 
+#ifdef CONFIG_RCU_TRACE
+struct rcupreempt_trace;
+extern int *rcupreempt_flipctr(int cpu);
+extern long rcupreempt_data_completed(void);
+extern int rcupreempt_flip_flag(int cpu);
+extern int rcupreempt_mb_flag(int cpu);
+extern char *rcupreempt_try_flip_state_name(void);
+extern struct rcupreempt_trace *rcupreempt_trace(void);
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __LINUX_RCUPREEMPT_H */
diff -puN /dev/null include/linux/rcupreempt_trace.h
--- /dev/null   2006-03-26 18:34:52.000000000 +0530
+++ linux-2.6.20-rc3-mm1-rcu-dipankar/include/linux/rcupreempt_trace.h  
2007-01-15 15:36:56.000000000 +0530
@@ -0,0 +1,102 @@
+/*
+ * Read-Copy Update mechanism for mutual exclusion (RT implementation)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation, 2006
+ *
+ * Author:  Paul McKenney <[EMAIL PROTECTED]>
+ * 
+ * Based on the original work by Paul McKenney <[EMAIL PROTECTED]>
+ * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.
+ * Papers:
+ * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf
+ * http://lse.sourceforge.net/locking/rclock_OLS.2001.05.01c.sc.pdf (OLS2001)
+ *
+ * For detailed explanation of Read-Copy Update mechanism see -
+ *             http://lse.sourceforge.net/locking/rcupdate.html
+ *
+ */
+
+#ifndef __LINUX_RCUPREEMPT_TRACE_H
+#define __LINUX_RCUPREEMPT_TRACE_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <asm/atomic.h>
+
+/*
+ * PREEMPT_RCU data structures.
+ */
+
+struct rcupreempt_trace {
+       long            next_length;
+       long            next_add;
+       long            wait_length;
+       long            wait_add;
+       long            done_length;
+       long            done_add;
+       long            done_remove;
+       atomic_t        done_invoked;
+       long            check_callbacks;
+       atomic_t        try_flip1;
+       long            try_flip2;
+       long            try_flip3;
+       atomic_t        try_flip_e1;
+       long            try_flip_i1;
+       long            try_flip_ie1;
+       long            try_flip_g1;
+       long            try_flip_a1;
+       long            try_flip_ae1;
+       long            try_flip_a2;
+       long            try_flip_z1;
+       long            try_flip_ze1;
+       long            try_flip_z2;
+       long            try_flip_m1;
+       long            try_flip_me1;
+       long            try_flip_m2;
+};
+
+#ifdef CONFIG_RCU_TRACE
+#define RCU_TRACE(fn, arg)     fn(arg);
+#else
+#define RCU_TRACE(fn, arg)
+#endif
+
+extern void rcupreempt_trace_move2done(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_move2wait(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_e1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_i1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_ie1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_g1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_a1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_ae1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_a2(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_z1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_ze1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_z2(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_m1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_me1(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_try_flip_m2(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_check_callbacks(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_done_remove(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_invoke(struct rcupreempt_trace *trace);
+extern void rcupreempt_trace_next_add(struct rcupreempt_trace *trace);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_RCUPREEMPT_TRACE_H */
diff -puN kernel/Kconfig.preempt~rcu-preempt-trace kernel/Kconfig.preempt
--- linux-2.6.20-rc3-mm1-rcu/kernel/Kconfig.preempt~rcu-preempt-trace   
2007-01-15 15:36:56.000000000 +0530
+++ linux-2.6.20-rc3-mm1-rcu-dipankar/kernel/Kconfig.preempt    2007-01-15 
15:36:56.000000000 +0530
@@ -89,3 +89,14 @@ config PREEMPT_RCU
          Say N if you are unsure.
 
 endchoice
+
+config RCU_TRACE
+       bool "Enable tracing for RCU - currently stats in debugfs"
+       select DEBUG_FS
+       default y
+       help
+         This option provides tracing in RCU which presents stats
+          in debugfs for debugging RCU implementation.
+ 
+         Say Y here if you want to enable RCU tracing
+         Say N if you are unsure.
diff -puN kernel/Makefile~rcu-preempt-trace kernel/Makefile
--- linux-2.6.20-rc3-mm1-rcu/kernel/Makefile~rcu-preempt-trace  2007-01-15 
15:36:56.000000000 +0530
+++ linux-2.6.20-rc3-mm1-rcu-dipankar/kernel/Makefile   2007-01-15 
15:36:56.000000000 +0530
@@ -48,6 +48,9 @@ obj-$(CONFIG_SECCOMP) += seccomp.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_CLASSIC_RCU) += rcuclassic.o
 obj-$(CONFIG_PREEMPT_RCU) += rcupreempt.o
+ifeq ($(CONFIG_PREEMPT_RCU),y)
+obj-$(CONFIG_RCU_TRACE) += rcupreempt_trace.o
+endif
 obj-$(CONFIG_DEBUG_SYNCHRO_TEST) += synchro-test.o
 obj-$(CONFIG_RELAY) += relay.o
 obj-$(CONFIG_UTS_NS) += utsname.o
diff -puN kernel/rcupreempt.c~rcu-preempt-trace kernel/rcupreempt.c
--- linux-2.6.20-rc3-mm1-rcu/kernel/rcupreempt.c~rcu-preempt-trace      
2007-01-15 15:36:56.000000000 +0530
+++ linux-2.6.20-rc3-mm1-rcu-dipankar/kernel/rcupreempt.c       2007-01-15 
15:36:56.000000000 +0530
@@ -50,6 +50,7 @@
 #include <linux/delay.h>
 #include <linux/byteorder/swabb.h>
 #include <linux/cpumask.h>
+#include <linux/rcupreempt_trace.h>
 
 /*
  * PREEMPT_RCU data structures.
@@ -64,6 +65,9 @@ struct rcu_data {
        struct rcu_head **waittail;
        struct rcu_head *donelist;
        struct rcu_head **donetail;
+#ifdef CONFIG_RCU_TRACE 
+       struct rcupreempt_trace trace;
+#endif /* #ifdef CONFIG_RCU_TRACE */
 };
 struct rcu_ctrlblk {
        spinlock_t      fliplock;
@@ -87,6 +91,10 @@ enum rcu_try_flip_state {
        RCU_TRY_FLIP_WAITMB     /* "M" */
 };
 static enum rcu_try_flip_state rcu_try_flip_state = RCU_TRY_FLIP_IDLE;
+#ifdef CONFIG_RCU_TRACE
+static char *rcu_try_flip_state_names[] =
+       { "idle", "gp", "waitack", "waitzero", "waitmb" };
+#endif /* #ifdef CONFIG_RCU_TRACE */
 
 /*
  * Enum and per-CPU flag to determine when each CPU has seen
@@ -249,12 +257,14 @@ static void __rcu_advance_callbacks(void
                if (rcu_data.waitlist != NULL) {
                        *rcu_data.donetail = rcu_data.waitlist;
                        rcu_data.donetail = rcu_data.waittail;
+                       RCU_TRACE(rcupreempt_trace_move2done, &rcu_data.trace);
                }
                if (rcu_data.nextlist != NULL) {
                        rcu_data.waitlist = rcu_data.nextlist;
                        rcu_data.waittail = rcu_data.nexttail;
                        rcu_data.nextlist = NULL;
                        rcu_data.nexttail = &rcu_data.nextlist;
+                       RCU_TRACE(rcupreempt_trace_move2wait, &rcu_data.trace);
                } else {
                        rcu_data.waitlist = NULL;
                        rcu_data.waittail = &rcu_data.waitlist;
@@ -275,8 +285,11 @@ static void __rcu_advance_callbacks(void
  */
 static int rcu_try_flip_idle(int flipctr)
 {
-       if (!rcu_pending(smp_processor_id()))
-               return 1;
+       RCU_TRACE(rcupreempt_trace_try_flip_i1, &rcu_data.trace);
+       if (!rcu_pending(smp_processor_id())) {
+               RCU_TRACE(rcupreempt_trace_try_flip_ie1, &rcu_data.trace);
+               return 1;
+       }
        return 0;
 }
 
@@ -288,6 +301,7 @@ static int rcu_try_flip_in_gp(int flipct
 {
        int cpu;
 
+       RCU_TRACE(rcupreempt_trace_try_flip_g1, &rcu_data.trace);
        /*
         * Do the flip.
         */
@@ -315,15 +329,19 @@ static int rcu_try_flip_waitack(int flip
 {
        int cpu;
 
+       RCU_TRACE(rcupreempt_trace_try_flip_a1, &rcu_data.trace);
        for_each_possible_cpu(cpu)
-               if (per_cpu(rcu_flip_flag, cpu) != RCU_FLIP_SEEN) 
-                       return 1;
-
+               if (per_cpu(rcu_flip_flag, cpu) != RCU_FLIP_SEEN) {
+                       RCU_TRACE(rcupreempt_trace_try_flip_ae1, 
+                                                       &rcu_data.trace);
+                       return 1;
+               }
        /*
         * Make sure our checks above don't bleed into subsequent
         * waiting for the sum of the counters to reach zero.
         */
        smp_mb();
+       RCU_TRACE(rcupreempt_trace_try_flip_a2, &rcu_data.trace);
        return 0;
 }
 
@@ -337,13 +355,17 @@ static int rcu_try_flip_waitzero(int fli
        int lastidx = !(flipctr & 0x1);
        int sum = 0;
 
+       RCU_TRACE(rcupreempt_trace_try_flip_z1, &rcu_data.trace);
        /* Check to see if the sum of the "last" counters is zero. */
 
        for_each_possible_cpu(cpu)
                sum += per_cpu(rcu_flipctr, cpu)[lastidx];
-       if (sum != 0)
+       if (sum != 0) {
+               RCU_TRACE(rcupreempt_trace_try_flip_ze1, &rcu_data.trace);
                return 1;
+       }
 
+       RCU_TRACE(rcupreempt_trace_try_flip_z2, &rcu_data.trace);
        /* Make sure we don't call for memory barriers before we see zero. */
        smp_mb();
 
@@ -362,11 +384,16 @@ static int rcu_try_flip_waitmb(int flipc
 {
        int cpu;
 
+       RCU_TRACE(rcupreempt_trace_try_flip_m1, &rcu_data.trace);
        for_each_possible_cpu(cpu)
-               if (per_cpu(rcu_mb_flag, cpu) != RCU_MB_DONE)
+               if (per_cpu(rcu_mb_flag, cpu) != RCU_MB_DONE) {
+                       RCU_TRACE(rcupreempt_trace_try_flip_me1, 
+                                                       &rcu_data.trace);
                        return 1;
+               }
 
        smp_mb(); /* Ensure that the above checks precede any following flip. */
+       RCU_TRACE(rcupreempt_trace_try_flip_m2, &rcu_data.trace);
        return 0;
 }
 
@@ -384,8 +411,11 @@ static void rcu_try_flip(void)
        long flipctr;
        unsigned long oldirq;
 
-       if (unlikely(!spin_trylock_irqsave(&rcu_ctrlblk.fliplock, oldirq))) 
+       RCU_TRACE(rcupreempt_trace_try_flip1, &rcu_data.trace);
+       if (unlikely(!spin_trylock_irqsave(&rcu_ctrlblk.fliplock, oldirq))) {
+               RCU_TRACE(rcupreempt_trace_try_flip_e1, &rcu_data.trace);
                return;
+       }
 
        /*
         * Take the next transition(s) through the RCU grace-period
@@ -462,6 +492,7 @@ void rcu_check_callbacks(int cpu, int us
                }
        }
        spin_lock_irqsave(&rcu_data.lock, oldirq);
+       RCU_TRACE(rcupreempt_trace_check_callbacks, &rcu_data.trace);
        __rcu_advance_callbacks();
        if (rcu_data.donelist == NULL)
                spin_unlock_irqrestore(&rcu_data.lock, oldirq);
@@ -514,11 +545,13 @@ static void rcu_process_callbacks(struct
        }
        rcu_data.donelist = NULL;
        rcu_data.donetail = &rcu_data.donelist;
+       RCU_TRACE(rcupreempt_trace_done_remove, &rcu_data.trace);
        spin_unlock_irqrestore(&rcu_data.lock, flags);
        while (list) {
                next = list->next;
                list->func(list);
                list = next;
+               RCU_TRACE(rcupreempt_trace_invoke, &rcu_data.trace);
        }
 }
 
@@ -533,6 +566,7 @@ void fastcall call_rcu(struct rcu_head *
        __rcu_advance_callbacks();
        *rcu_data.nexttail = head;
        rcu_data.nexttail = &head->next;
+       RCU_TRACE(rcupreempt_trace_next_add, &rcu_data.trace);
        spin_unlock_irqrestore(&rcu_data.lock, flags);
 }
 
@@ -585,6 +619,37 @@ void synchronize_kernel(void)
        synchronize_rcu();
 }
 
+#ifdef RCU_TRACE
+int *rcupreempt_flipctr(int cpu)
+{
+       return &per_cpu(rcu_flipctr, cpu)[0];
+}
+long rcupreempt_data_completed(void)
+{
+       return rcu_data.completed;
+}
+int rcupreempt_flip_flag(int cpu)
+{
+       return per_cpu(rcu_flip_flag, cpu);
+}
+int rcupreempt_mb_flag(int cpu)
+{
+       return per_cpu(rcu_mb_flag, cpu);
+}
+char *rcupreempt_try_flip_state_name(void)
+{
+       return rcu_try_flip_state_names[rcu_try_flip_state];
+}
+struct rcupreempt_trace *rcupreempt_trace(void)
+{
+       return &rcu_data.trace;
+}
+EXPORT_SYMBOL_GPL(rcupreempt_flipctr);
+EXPORT_SYMBOL_GPL(rcupreempt_data_completed);
+EXPORT_SYMBOL_GPL(rcupreempt_flip_flag);
+EXPORT_SYMBOL_GPL(rcupreempt_mb_flag);
+EXPORT_SYMBOL_GPL(rcupreempt_try_flip_state_name);
+#endif /* #ifdef RCU_TRACE */
 
 EXPORT_SYMBOL_GPL(call_rcu);
 EXPORT_SYMBOL_GPL(rcu_batches_completed);
diff -puN /dev/null kernel/rcupreempt_trace.c
--- /dev/null   2006-03-26 18:34:52.000000000 +0530
+++ linux-2.6.20-rc3-mm1-rcu-dipankar/kernel/rcupreempt_trace.c 2007-01-15 
15:36:56.000000000 +0530
@@ -0,0 +1,308 @@
+/*
+ * Read-Copy Update tracing for realtime implementation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright IBM Corporation, 2006
+ *
+ * Papers:  http://www.rdrop.com/users/paulmck/RCU
+ *
+ * For detailed explanation of Read-Copy Update mechanism see -
+ *             Documentation/RCU/ *.txt
+ *
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/rcupdate.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <asm/atomic.h>
+#include <linux/bitops.h>
+#include <linux/module.h>
+#include <linux/completion.h>
+#include <linux/moduleparam.h>
+#include <linux/percpu.h>
+#include <linux/notifier.h>
+#include <linux/rcupdate.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+#include <linux/rcupreempt_trace.h>
+#include <linux/debugfs.h>
+
+static struct mutex rcupreempt_trace_mutex;
+static char *rcupreempt_trace_buf;
+#define RCUPREEMPT_TRACE_BUF_SIZE 4096
+
+void rcupreempt_trace_move2done(struct rcupreempt_trace *trace)
+{
+       trace->done_length += trace->wait_length;
+       trace->done_add += trace->wait_length;
+       trace->wait_length = 0;
+}
+void rcupreempt_trace_move2wait(struct rcupreempt_trace *trace)
+{
+       trace->wait_length += trace->next_length;
+       trace->wait_add += trace->next_length;
+       trace->next_length = 0;
+}
+void rcupreempt_trace_try_flip1(struct rcupreempt_trace *trace)
+{
+       atomic_inc(&trace->try_flip1);
+}
+void rcupreempt_trace_try_flip_e1(struct rcupreempt_trace *trace)
+{
+       atomic_inc(&trace->try_flip_e1);
+}
+void rcupreempt_trace_try_flip2(struct rcupreempt_trace *trace)
+{
+       trace->try_flip2++;
+}
+void rcupreempt_trace_try_flip3(struct rcupreempt_trace *trace)
+{
+       trace->try_flip3++;
+}
+void rcupreempt_trace_try_flip_i1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_i1++;
+}
+void rcupreempt_trace_try_flip_ie1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_ie1++;
+}
+void rcupreempt_trace_try_flip_g1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_g1++;
+}
+void rcupreempt_trace_try_flip_a1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_a1++;
+}
+void rcupreempt_trace_try_flip_ae1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_ae1++;
+}
+void rcupreempt_trace_try_flip_a2(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_a2++;
+}
+void rcupreempt_trace_try_flip_z1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_z1++;
+}
+void rcupreempt_trace_try_flip_ze1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_ze1++;
+}
+void rcupreempt_trace_try_flip_z2(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_z2++;
+}
+void rcupreempt_trace_try_flip_m1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_m1++;
+}
+void rcupreempt_trace_try_flip_me1(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_me1++;
+}
+void rcupreempt_trace_try_flip_m2(struct rcupreempt_trace *trace)
+{
+       trace->try_flip_m2++;
+}
+void rcupreempt_trace_check_callbacks(struct rcupreempt_trace *trace)
+{
+       trace->check_callbacks++;
+}
+void rcupreempt_trace_done_remove(struct rcupreempt_trace *trace)
+{
+       trace->done_remove += trace->done_length;
+       trace->done_length = 0;
+}
+void rcupreempt_trace_invoke(struct rcupreempt_trace *trace)
+{
+       atomic_inc(&trace->done_invoked);
+}
+void rcupreempt_trace_next_add(struct rcupreempt_trace *trace)
+{
+        trace->next_add++;
+        trace->next_length++;
+}
+
+static ssize_t rcustats_read(struct file *filp, char __user *buffer,
+                               size_t count, loff_t *ppos)
+{
+       struct rcupreempt_trace *trace = rcupreempt_trace();
+       ssize_t bcount;
+
+       mutex_lock(&rcupreempt_trace_mutex);
+       snprintf(rcupreempt_trace_buf, RCUPREEMPT_TRACE_BUF_SIZE,
+                      "ggp=%ld lgp=%ld rcc=%ld\n"
+                      "na=%ld nl=%ld wa=%ld wl=%ld da=%ld dl=%ld dr=%ld 
di=%d\n"
+                      "1=%d e1=%d i1=%ld ie1=%ld g1=%ld a1=%ld ae1=%ld 
a2=%ld\n"
+                      "z1=%ld ze1=%ld z2=%ld m1=%ld me1=%ld m2=%ld\n",
+
+                      rcu_batches_completed(),
+                      rcupreempt_data_completed(),
+                      trace->check_callbacks,
+                      trace->next_add,
+                      trace->next_length,
+                      trace->wait_add,
+                      trace->wait_length,
+                      trace->done_add,
+                      trace->done_length,
+                      trace->done_remove,
+                      atomic_read(&trace->done_invoked),
+                      atomic_read(&trace->try_flip1),
+                      atomic_read(&trace->try_flip_e1),
+                      trace->try_flip_i1,
+                      trace->try_flip_ie1,
+                      trace->try_flip_g1,
+                      trace->try_flip_a1,
+                      trace->try_flip_ae1,
+                      trace->try_flip_a2,
+                      trace->try_flip_z1,
+                      trace->try_flip_ze1,
+                      trace->try_flip_z2,
+                      trace->try_flip_m1,
+                      trace->try_flip_me1,
+                      trace->try_flip_m2);
+       bcount = simple_read_from_buffer(buffer, count, ppos, 
+                       rcupreempt_trace_buf, strlen(rcupreempt_trace_buf));
+       mutex_unlock(&rcupreempt_trace_mutex);
+       return bcount;
+}
+
+static ssize_t rcugp_read(struct file *filp, char __user *buffer,
+                               size_t count, loff_t *ppos)
+{
+       long oldgp = rcu_batches_completed();
+       ssize_t bcount;
+
+       mutex_lock(&rcupreempt_trace_mutex);
+       synchronize_rcu();
+       snprintf(rcupreempt_trace_buf, RCUPREEMPT_TRACE_BUF_SIZE, 
+               "oldggp=%ld  newggp=%ld\n", oldgp, rcu_batches_completed());
+       bcount = simple_read_from_buffer(buffer, count, ppos, 
+                       rcupreempt_trace_buf, strlen(rcupreempt_trace_buf));
+       mutex_unlock(&rcupreempt_trace_mutex);
+       return bcount;
+}
+
+static ssize_t rcuctrs_read(struct file *filp, char __user *buffer,
+                               size_t count, loff_t *ppos)
+{
+       int cnt = 0;
+       int cpu;
+       int f = rcu_batches_completed() & 0x1;
+       ssize_t bcount;
+
+       mutex_lock(&rcupreempt_trace_mutex);
+
+       cnt += snprintf(&rcupreempt_trace_buf[cnt], RCUPREEMPT_TRACE_BUF_SIZE, 
+                               "CPU last cur F M\n");
+       for_each_online_cpu(cpu) {
+               int *flipctr = rcupreempt_flipctr(cpu);
+               cnt += snprintf(&rcupreempt_trace_buf[cnt], 
+                               RCUPREEMPT_TRACE_BUF_SIZE - cnt,
+                                       "%3d %4d %3d %d %d\n",
+                              cpu,
+                              flipctr[!f],
+                              flipctr[f],
+                              rcupreempt_flip_flag(cpu),
+                              rcupreempt_mb_flag(cpu));
+       }
+       cnt += snprintf(&rcupreempt_trace_buf[cnt],
+                       RCUPREEMPT_TRACE_BUF_SIZE - cnt,
+                       "ggp = %ld, state = %s\n",
+                       rcupreempt_data_completed(), 
+                       rcupreempt_try_flip_state_name());
+       cnt += snprintf(&rcupreempt_trace_buf[cnt], 
+                       RCUPREEMPT_TRACE_BUF_SIZE - cnt,
+                       "\n");
+       bcount = simple_read_from_buffer(buffer, count, ppos, 
+                       rcupreempt_trace_buf, strlen(rcupreempt_trace_buf));
+       mutex_unlock(&rcupreempt_trace_mutex);
+       return bcount;
+}
+
+static struct file_operations rcustats_fops = {
+       .owner = THIS_MODULE,
+       .read = rcustats_read,
+};
+
+static struct file_operations rcugp_fops = {
+       .owner = THIS_MODULE,
+       .read = rcugp_read,
+};
+
+static struct file_operations rcuctrs_fops = {
+       .owner = THIS_MODULE,
+       .read = rcuctrs_read,
+};
+
+static struct dentry *rcudir, *statdir, *ctrsdir, *gpdir;
+static int rcupreempt_debugfs_init(void)
+{
+       rcudir = debugfs_create_dir("rcu", NULL);
+       if (!rcudir)
+               goto out;
+       statdir = debugfs_create_file("rcustats", 0444, rcudir, 
+                                               NULL, &rcustats_fops);
+       if (!statdir)
+               goto free_out;
+
+       gpdir = debugfs_create_file("rcugp", 0444, rcudir, NULL, &rcugp_fops);
+       if (!gpdir)
+               goto free_out;
+
+       ctrsdir = debugfs_create_file("rcuctrs", 0444, rcudir, 
+                                               NULL, &rcuctrs_fops);
+       if (!ctrsdir)
+               goto free_out;
+       return 0;
+free_out:
+       if (statdir)
+               debugfs_remove(statdir);
+       if (gpdir)
+               debugfs_remove(gpdir);
+       debugfs_remove(rcudir);
+out:
+       return 1;
+}
+
+static int __init rcupreempt_trace_init(void)
+{
+       mutex_init(&rcupreempt_trace_mutex);
+       rcupreempt_trace_buf = kmalloc(RCUPREEMPT_TRACE_BUF_SIZE, GFP_KERNEL);
+       if (!rcupreempt_trace_buf)
+               return 1;
+       return rcupreempt_debugfs_init();
+}
+
+static void __exit rcupreempt_trace_cleanup(void)
+{
+       debugfs_remove(statdir);
+       debugfs_remove(gpdir);
+       debugfs_remove(ctrsdir);
+       debugfs_remove(rcudir);
+       kfree(rcupreempt_trace_buf);
+}
+
+
+module_init(rcupreempt_trace_init);
+module_exit(rcupreempt_trace_cleanup);

_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to