From: Wolfgang Mauerer <wolfgang.maue...@siemens.com>

The entries depend on the number of CPUs and can thus overflow a single page.

Signed-off-by: Wolfgang Mauerer <wolfgang.maue...@siemens.com>
Signed-off-by: Jan Kiszka <jan.kis...@siemens.com>
---
 ksrc/arch/generic/hal.c |  148 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 118 insertions(+), 30 deletions(-)

diff --git a/ksrc/arch/generic/hal.c b/ksrc/arch/generic/hal.c
index c2239ca..ca221b5 100644
--- a/ksrc/arch/generic/hal.c
+++ b/ksrc/arch/generic/hal.c
@@ -47,6 +47,7 @@
 #include <asm/xenomai/hal.h>
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #endif /* CONFIG_PROC_FS */
 #include <stdarg.h>
 
@@ -642,46 +643,133 @@ static int hal_read_proc(char *page,
     return len;
 }
 
-static int faults_read_proc(char *page,
-                            char **start,
-                            off_t off, int count, int *eof, void *data)
+struct faults_seq_iterator {
+       unsigned int nentries;
+       struct faults_seq_info {
+               unsigned int trap;
+       } faults_info[0];
+};
+
+static int __faults_seq_open(struct inode *inode,
+                            struct file *file, struct seq_operations *ops)
 {
-    int len = 0, cpu, trap;
-    char *p = page;
+       struct faults_seq_iterator *iter = NULL;
+       struct faults_seq_info *faults_info;
+       struct seq_file *seq;
+       unsigned int ntraps = 0;
+       unsigned int trap;
+       int err;
+
+       for (trap = 0; rthal_fault_labels[trap] != NULL; trap++) {
+               if (!*rthal_fault_labels[trap])
+                       continue;
+               ntraps++;
+       }
 
-    p += sprintf(p, "TRAP ");
+       iter = kmalloc(sizeof(*iter)
+                      + ntraps * sizeof(struct faults_seq_info),
+                      GFP_KERNEL);
+       if (!iter)
+               return -ENOMEM;
 
-    for_each_online_cpu(cpu) {
-        p += sprintf(p, "        CPU%d", cpu);
-    }
+       err = seq_open(file, ops);
 
-    for (trap = 0; rthal_fault_labels[trap] != NULL; trap++) {
+       if (err) {
+               kfree(iter);
+               return err;
+       }
 
-        if (!*rthal_fault_labels[trap])
-            continue;
+       iter->nentries = 0;
 
-        p += sprintf(p, "\n%3d: ", trap);
+       for (trap = 0; rthal_fault_labels[trap] != NULL; trap++) {
+               if (!*rthal_fault_labels[trap])
+                       continue;
 
-        for_each_online_cpu(cpu) {
-            p += sprintf(p, "%12u", rthal_realtime_faults[cpu][trap]);
-        }
+               faults_info = &iter->faults_info[iter->nentries++];
 
-        p += sprintf(p, "    (%s)", rthal_fault_labels[trap]);
-    }
+               faults_info->trap = trap;
+       }
 
-    p += sprintf(p, "\n");
+       seq = file->private_data;
+       seq->private = iter;
 
-    len = p - page - off;
-    if (len <= off + count)
-        *eof = 1;
-    *start = page + off;
-    if (len > count)
-        len = count;
-    if (len < 0)
-        len = 0;
+       return 0;
+}
 
-    return len;
+static void *faults_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       struct faults_seq_iterator *iter = seq->private;
+
+       if (*pos > iter->nentries)
+               return NULL;
+
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+
+       return iter->faults_info + *pos - 1;
 }
+static void *faults_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct faults_seq_iterator *iter = seq->private;
+
+       (*pos)++;
+
+       if (*pos > iter->nentries)
+               return NULL;
+
+       return iter->faults_info + *pos - 1;
+}
+
+static void faults_seq_stop(struct seq_file *f, void *v)
+{
+       /* Nothing to do */
+}
+
+static int faults_seq_show(struct seq_file *f, void *v)
+{
+       unsigned int cpu;
+       struct faults_seq_info *p = v;
+
+       if (v == SEQ_START_TOKEN) {
+               seq_puts(f, "TRAP ");
+
+               for_each_online_cpu(cpu) {
+                       seq_printf(f, "        CPU%d\n", cpu);
+               }
+       }
+       else {
+               seq_printf(f, "%3d: ", p->trap);
+
+               for_each_online_cpu(cpu) {
+                       seq_printf(f, "%12u",
+                                  rthal_realtime_faults[cpu][p->trap]);
+               }
+
+               seq_printf(f, "    (%s)\n", rthal_fault_labels[p->trap]);
+       }
+
+       return 0;
+}
+
+static struct seq_operations faults_op = {
+       .start  = faults_seq_start,
+       .next   = faults_seq_next,
+       .stop   = faults_seq_stop,
+       .show   = faults_seq_show
+};
+
+static int faults_seq_open(struct inode *inode, struct file *file)
+{
+       return __faults_seq_open(inode, file, &faults_op);
+}
+
+static struct file_operations faults_seq_operations = {
+       .owner          = THIS_MODULE,
+       .open           = faults_seq_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release_private,
+};
 
 static int apc_read_proc(char *page,
                          char **start,
@@ -779,8 +867,8 @@ static int rthal_proc_register(void)
        wrap_proc_dir_entry_owner(rthal_proc_root);
 
        rthal_add_proc_leaf("hal", &hal_read_proc, NULL, NULL, rthal_proc_root);
-       rthal_add_proc_leaf("faults",
-                           &faults_read_proc, NULL, NULL, rthal_proc_root);
+       rthal_add_proc_seq("faults", &faults_seq_operations, 0,
+                          rthal_proc_root);
        rthal_add_proc_leaf("apc", &apc_read_proc, NULL, NULL, rthal_proc_root);
 
        rthal_nmi_proc_register();
-- 
1.6.0.2


_______________________________________________
Xenomai-core mailing list
Xenomai-core@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to