Module: xenomai-forge
Branch: next
Commit: 141b8a556df026ecde40e79113763a6bfd701846
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=141b8a556df026ecde40e79113763a6bfd701846

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Jul 30 19:30:55 2013 +0200

cobalt/arch: turn apc and fault statistics into per-cpu data

---

 include/cobalt/kernel/apc.h                        |    5 ++-
 kernel/cobalt/apc.c                                |   27 ++++++++++---------
 .../cobalt/include/asm-generic/xenomai/machine.h   |   12 ++++++--
 kernel/cobalt/init.c                               |    3 ++
 kernel/cobalt/procfs.c                             |    4 +-
 kernel/cobalt/shadow.c                             |   15 +++++++---
 6 files changed, 41 insertions(+), 25 deletions(-)

diff --git a/include/cobalt/kernel/apc.h b/include/cobalt/kernel/apc.h
index c18bceb..67aa735 100644
--- a/include/cobalt/kernel/apc.h
+++ b/include/cobalt/kernel/apc.h
@@ -37,8 +37,9 @@ void xnapc_free(int apc);
 
 static inline void __xnapc_schedule(int apc)
 {
-       int cpu = ipipe_processor_id();
-       if (!__test_and_set_bit(apc, &xnarch_machdata.apc_pending[cpu]))
+       unsigned long *p = 
&__this_cpu_ptr(&xnarch_percpu_machdata)->apc_pending;
+
+       if (!__test_and_set_bit(apc, p))
                ipipe_post_irq_root(xnarch_machdata.apc_virq);
 }
 
diff --git a/kernel/cobalt/apc.c b/kernel/cobalt/apc.c
index 25bb33d..b01f0c8 100644
--- a/kernel/cobalt/apc.c
+++ b/kernel/cobalt/apc.c
@@ -44,27 +44,28 @@ static IPIPE_DEFINE_SPINLOCK(apc_lock);
 void apc_dispatch(unsigned int virq, void *arg)
 {
        void (*handler)(void *), *cookie;
-       int apc, cpu;
-
-       spin_lock(&apc_lock);
-
-       cpu = ipipe_processor_id();
+       unsigned long *p;
+       int apc;
 
        /*
-        * <!> This loop is not protected against a handler becoming
-        * unavailable while processing the pending queue; the
-        * software must make sure to uninstall all APCs before
-        * eventually unloading any module that may contain APC
+        * CAUTION: The APC dispatch loop is not protected against a
+        * handler becoming unavailable while processing the pending
+        * queue; the software must make sure to uninstall all APCs
+        * before eventually unloading any module that may contain APC
         * handlers. We keep the handler affinity with the poster's
         * CPU, so that the handler is invoked on the same CPU than
         * the code which called xnapc_schedule().
         */
-       while (xnarch_machdata.apc_pending[cpu]) {
-               apc = ffnz(xnarch_machdata.apc_pending[cpu]);
-               clear_bit(apc, &xnarch_machdata.apc_pending[cpu]);
+       spin_lock(&apc_lock);
+
+       /* This is atomic linux context (non-threaded IRQ). */
+       p = &__this_cpu_ptr(&xnarch_percpu_machdata)->apc_pending;
+       while (*p) {
+               apc = ffnz(*p);
+               clear_bit(apc, p);
                handler = xnarch_machdata.apc_table[apc].handler;
                cookie = xnarch_machdata.apc_table[apc].cookie;
-               xnarch_machdata.apc_table[apc].hits[cpu]++;
+               __this_cpu_ptr(&xnarch_percpu_machdata)->apc_shots[apc]++;
                spin_unlock(&apc_lock);
                handler(cookie);
                spin_lock(&apc_lock);
diff --git a/kernel/cobalt/include/asm-generic/xenomai/machine.h 
b/kernel/cobalt/include/asm-generic/xenomai/machine.h
index a32e63c..b6b4e8e 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/machine.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/machine.h
@@ -24,6 +24,7 @@
 #endif
 
 #include <linux/ipipe.h>
+#include <linux/percpu.h>
 #include <asm/byteorder.h>
 #include <asm/xenomai/wrappers.h>
 
@@ -40,21 +41,26 @@ struct xnarch_machdesc {
 
 extern struct xnarch_machdesc xnarch_machdesc;
 
+struct xnarch_percpu_machdata {
+       unsigned long apc_pending;
+       unsigned long apc_shots[BITS_PER_LONG];
+       unsigned int faults[IPIPE_NR_FAULTS];
+};
+
+DECLARE_PER_CPU(struct xnarch_percpu_machdata, xnarch_percpu_machdata);
+
 struct xnarch_machdata {
        struct ipipe_domain domain;
        unsigned long timer_freq;
        unsigned long clock_freq;
        unsigned int apc_virq;
        unsigned long apc_map;
-       unsigned long apc_pending[NR_CPUS];
        unsigned int escalate_virq;
        struct {
                void (*handler)(void *cookie);
                void *cookie;
                const char *name;
-               unsigned long hits[NR_CPUS];
        } apc_table[BITS_PER_LONG];
-       unsigned int faults[NR_CPUS][IPIPE_NR_FAULTS];
 #ifdef CONFIG_SMP
        cpumask_t supported_cpus;
 #endif
diff --git a/kernel/cobalt/init.c b/kernel/cobalt/init.c
index 2f3a4da..6604833 100644
--- a/kernel/cobalt/init.c
+++ b/kernel/cobalt/init.c
@@ -58,6 +58,9 @@ module_param_named(disable, disable_arg, ulong, 0444);
 struct xnarch_machdata xnarch_machdata;
 EXPORT_SYMBOL_GPL(xnarch_machdata);
 
+struct xnarch_percpu_machdata xnarch_percpu_machdata;
+EXPORT_PER_CPU_SYMBOL_GPL(xnarch_percpu_machdata);
+
 struct xnsys_ppd __xnsys_global_ppd = {
        .exe_path = "vmlinux",
 };
diff --git a/kernel/cobalt/procfs.c b/kernel/cobalt/procfs.c
index dd1c32b..e0504d7 100644
--- a/kernel/cobalt/procfs.c
+++ b/kernel/cobalt/procfs.c
@@ -157,7 +157,7 @@ static int faults_vfile_show(struct 
xnvfile_regular_iterator *it, void *data)
 
                for_each_online_cpu(cpu)
                        xnvfile_printf(it, "%12u",
-                                      xnarch_machdata.faults[cpu][trap]);
+                                      per_cpu(xnarch_percpu_machdata, 
cpu).faults[trap]);
 
                xnvfile_printf(it, "    (%s)",
                               xnarch_machdesc.fault_labels[trap]);
@@ -195,7 +195,7 @@ static int apc_vfile_show(struct xnvfile_regular_iterator 
*it, void *data)
 
                for_each_online_cpu(cpu)
                        xnvfile_printf(it, "%12lu",
-                                      
xnarch_machdata.apc_table[apc].hits[cpu]);
+                                      per_cpu(xnarch_percpu_machdata, 
cpu).apc_shots[apc]);
 
                if (xnarch_machdata.apc_table[apc].name)
                        xnvfile_printf(it, "    (%s)",
diff --git a/kernel/cobalt/shadow.c b/kernel/cobalt/shadow.c
index 9afbe5e..a10f46c 100644
--- a/kernel/cobalt/shadow.c
+++ b/kernel/cobalt/shadow.c
@@ -2463,15 +2463,20 @@ int ipipe_trap_hook(struct ipipe_trap_data *data)
                return handle_mayday_event(data->regs);
 
        /*
-        * CAUTION: access faults must be propagated downstream
-        * whichever domain caused them, so that we don't spuriously
-        * raise a fatal error when some Linux fixup code is available
-        * to solve the error condition.
+        * No migration is possible on behalf of the head domain, so
+        * the following access is safe.
         */
-       xnarch_machdata.faults[ipipe_processor_id()][data->exception]++;
+       __this_cpu_ptr(&xnarch_percpu_machdata)->faults[data->exception]++;
+
        if (xnpod_handle_exception(data))
                return EVENT_STOP;
 
+       /*
+        * CAUTION: access faults must be propagated downstream
+        * whichever domain caused them, so that we don't spuriously
+        * raise a fatal error when some Linux fixup code is available
+        * to recover from the fault.
+        */
        return EVENT_PROPAGATE;
 }
 


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to