Module: xenomai-rpm
Branch: queue/vfile
Commit: 77b99bdbac790c51da9a1a0263178c1c7a9e63a8
URL:    
http://git.xenomai.org/?p=xenomai-rpm.git;a=commit;h=77b99bdbac790c51da9a1a0263178c1c7a9e63a8

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue May 25 16:27:57 2010 +0200

nucleus/sched: convert to vfile

---

 include/nucleus/pod.h         |   13 +-
 include/nucleus/sched.h       |    9 +-
 ksrc/nucleus/pod.c            |   16 +-
 ksrc/nucleus/sched-idle.c     |    1 -
 ksrc/nucleus/sched-rt.c       |  229 ++++++---------
 ksrc/nucleus/sched-sporadic.c |  247 +++++++---------
 ksrc/nucleus/sched-tp.c       |  213 ++++++--------
 ksrc/nucleus/sched.c          |  671 +++++++++++++++++-----------------------
 8 files changed, 592 insertions(+), 807 deletions(-)

diff --git a/include/nucleus/pod.h b/include/nucleus/pod.h
index 8831fb5..8356706 100644
--- a/include/nucleus/pod.h
+++ b/include/nucleus/pod.h
@@ -71,8 +71,9 @@ struct xnpod {
        xnsched_t sched[XNARCH_NR_CPUS];        /*!< Per-cpu scheduler slots. */
 
        xnqueue_t threadq;      /*!< All existing threads. */
-       int threadq_rev;        /*!< Modification counter of threadq. */
-
+#ifdef CONFIG_PROC_FS
+       struct xnvfile_rev_tag threadlist_tag;
+#endif
        xnqueue_t tstartq,      /*!< Thread start hook queue. */
         tswitchq,              /*!< Thread switch hook queue. */
         tdeleteq;              /*!< Thread delete hook queue. */
@@ -104,17 +105,17 @@ extern xnarch_cpumask_t nkaffinity;
 extern xnpod_t nkpod_struct;
 
 #ifdef CONFIG_PROC_FS
-void xnpod_init_proc(void);
+int xnpod_init_proc(void);
 void xnpod_cleanup_proc(void);
 #else /* !CONFIG_PROC_FS */
-static inline void xnpod_init_proc(void) {}
+static inline int xnpod_init_proc(void) { return 0; }
 static inline void xnpod_cleanup_proc(void) {}
 #endif /* !CONFIG_PROC_FS */
 
-static inline void xnpod_mount(void)
+static inline int xnpod_mount(void)
 {
        xnsched_register_classes();
-       xnpod_init_proc();
+       return xnpod_init_proc();
 }
 
 static inline void xnpod_umount(void)
diff --git a/include/nucleus/sched.h b/include/nucleus/sched.h
index 441a3a2..f8cc059 100644
--- a/include/nucleus/sched.h
+++ b/include/nucleus/sched.h
@@ -35,6 +35,7 @@
 #include <nucleus/schedqueue.h>
 #include <nucleus/sched-tp.h>
 #include <nucleus/sched-sporadic.h>
+#include <nucleus/vfile.h>
 
 /* Sched status flags */
 #define XNKCOUT                0x80000000      /* Sched callout context */
@@ -141,9 +142,9 @@ struct xnsched_class {
        void (*sched_resume_rpi)(struct xnthread *thread);
 #endif
 #ifdef CONFIG_PROC_FS
-       void (*sched_init_proc)(struct proc_dir_entry *root);
-       void (*sched_cleanup_proc)(struct proc_dir_entry *root);
-       struct proc_dir_entry *proc;
+       int (*sched_init_vfile)(struct xnsched_class *schedclass,
+                               struct xnvfile_directory *vfroot);
+       void (*sched_cleanup_vfile)(struct xnsched_class *schedclass);
 #endif
        int nthreads;
        struct xnsched_class *next;
@@ -242,7 +243,7 @@ static inline void xnsched_reset_watchdog(struct xnsched 
*sched)
 #include <nucleus/sched-idle.h>
 #include <nucleus/sched-rt.h>
 
-void xnsched_init_proc(void);
+int xnsched_init_proc(void);
 
 void xnsched_cleanup_proc(void);
 
diff --git a/ksrc/nucleus/pod.c b/ksrc/nucleus/pod.c
index 7002a73..7e8a3b7 100644
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -652,7 +652,7 @@ int xnpod_init_thread(struct xnthread *thread,
 
        xnlock_get_irqsave(&nklock, s);
        appendq(&nkpod->threadq, &thread->glink);
-       nkpod->threadq_rev++;
+       xnvfile_touch_tag(&nkpod->threadlist_tag);
        xnpod_suspend_thread(thread, XNDORMANT | (attr->flags & XNSUSP), 
XN_INFINITE,
                             XN_RELATIVE, NULL);
        xnlock_put_irqrestore(&nklock, s);
@@ -1174,7 +1174,7 @@ void xnpod_delete_thread(xnthread_t *thread)
                   thread, xnthread_name(thread));
 
        removeq(&nkpod->threadq, &thread->glink);
-       nkpod->threadq_rev++;
+       xnvfile_touch_tag(&nkpod->threadlist_tag);
 
        if (xnthread_test_state(thread, XNREADY)) {
                XENO_BUGON(NUCLEUS, xnthread_test_state(thread, 
XNTHREAD_BLOCK_BITS));
@@ -3203,12 +3203,17 @@ static int version_read_proc(char *page,
        return len;
 }
 
-void xnpod_init_proc(void)
+int xnpod_init_proc(void)
 {
+       int ret;
+
        if (rthal_proc_root == NULL)
-               return;
+               return -ENOMEM;
+
+       ret = xnsched_init_proc();
+       if (ret)
+               return ret;
 
-       xnsched_init_proc();
        xntbase_init_proc();
        xntimer_init_proc();
        xnheap_init_proc();
@@ -3226,6 +3231,7 @@ void xnpod_init_proc(void)
        rthal_add_proc_leaf("lock", &lock_read_proc, NULL, NULL,
                            rthal_proc_root);
 #endif /* XENO_DEBUG(XNLOCK) */
+       return 0;
 }
 
 void xnpod_cleanup_proc(void)
diff --git a/ksrc/nucleus/sched-idle.c b/ksrc/nucleus/sched-idle.c
index 39faa6a..124cd67 100644
--- a/ksrc/nucleus/sched-idle.c
+++ b/ksrc/nucleus/sched-idle.c
@@ -48,7 +48,6 @@ void xnsched_idle_trackprio(struct xnthread *thread,
 }
 
 struct xnsched_class xnsched_class_idle = {
-
        .sched_init             =       NULL,
        .sched_enqueue          =       NULL,
        .sched_dequeue          =       NULL,
diff --git a/ksrc/nucleus/sched-rt.c b/ksrc/nucleus/sched-rt.c
index 7483166..ca3a2c2 100644
--- a/ksrc/nucleus/sched-rt.c
+++ b/ksrc/nucleus/sched-rt.c
@@ -157,62 +157,95 @@ static struct xnthread *xnsched_rt_peek_rpi(struct 
xnsched *sched)
 
 #ifdef CONFIG_PROC_FS
 
-#include <linux/seq_file.h>
-
-struct xnsched_rt_seq_iterator {
-       xnticks_t start_time;
-       int nentries;
-       struct xnsched_rt_info {
-               int cpu;
-               pid_t pid;
-               char name[XNOBJECT_NAME_LEN];
-               xnticks_t period;
-               int periodic;
-               int cprio;
-               int dnprio;
-       } sched_info[1];
+struct xnvfile_directory sched_rt_vfroot;
+
+struct vfile_sched_rt_priv {
+       int nrthreads;
+       struct xnholder *curr;
 };
 
-static void *xnsched_rt_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       struct xnsched_rt_seq_iterator *iter = seq->private;
+struct vfile_sched_rt_data {
+       int cpu;
+       pid_t pid;
+       char name[XNOBJECT_NAME_LEN];
+       xnticks_t period;
+       int periodic;
+       int cprio;
+       int dnprio;
+};
 
-       if (*pos > iter->nentries)
-               return NULL;
+static struct xnvfile_snapshot_ops vfile_sched_rt_ops;
 
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
+static struct xnvfile_snapshot vfile_sched_rt = {
+       .privsz = sizeof(struct vfile_sched_rt_priv),
+       .datasz = sizeof(struct vfile_sched_rt_data),
+       .tag = &nkpod_struct.threadlist_tag,
+       .ops = &vfile_sched_rt_ops,
+};
+
+static int vfile_sched_rt_rewind(struct xnvfile_snapshot_iterator *it)
+{
+       struct vfile_sched_rt_priv *priv = xnvfile_snapshot_iterator_priv(it);
 
-       return iter->sched_info + *pos - 1;
+       priv->nrthreads = xnsched_class_rt.nthreads;
+       if (priv->nrthreads == 0)
+               return -ESRCH;
+       priv->curr = getheadq(&nkpod->threadq);
+
+       return 0;
 }
 
-static void *xnsched_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *vfile_sched_rt_begin(struct xnvfile_snapshot_iterator *it)
 {
-       struct xnsched_rt_seq_iterator *iter = seq->private;
+       struct vfile_sched_rt_priv *priv = xnvfile_snapshot_iterator_priv(it);
 
-       ++*pos;
-
-       if (*pos > iter->nentries)
-               return NULL;
+       return kmalloc(priv->nrthreads * sizeof(struct vfile_sched_rt_data),
+                      GFP_KERNEL);
+}
 
-       return iter->sched_info + *pos - 1;
+static void vfile_sched_rt_end(struct xnvfile_snapshot_iterator *it,
+                              void *buf)
+{
+       kfree(buf);
 }
 
-static void xnsched_rt_seq_stop(struct seq_file *seq, void *v)
+static int vfile_sched_rt_next(struct xnvfile_snapshot_iterator *it,
+                              void *data)
 {
+       struct vfile_sched_rt_priv *priv = xnvfile_snapshot_iterator_priv(it);
+       struct vfile_sched_rt_data *p = data;
+       struct xnthread *thread;
+
+       if (priv->curr == NULL)
+               return 0;       /* All done. */
+
+       thread = link2thread(priv->curr, glink);
+       priv->curr = nextq(&nkpod->threadq, priv->curr);
+
+       if (thread->base_class != &xnsched_class_rt)
+               return VFILE_SEQ_SKIP;
+
+       p->cpu = xnsched_cpu(thread->sched);
+       p->pid = xnthread_user_pid(thread);
+       memcpy(p->name, thread->name, sizeof(p->name));
+       p->cprio = thread->cprio;
+       p->dnprio = xnthread_get_denormalized_prio(thread, thread->cprio);
+       p->period = xnthread_get_period(thread);
+       p->periodic = xntbase_periodic_p(xnthread_time_base(thread));
+
+       return 1;
 }
 
-static int xnsched_rt_seq_show(struct seq_file *seq, void *v)
+static int vfile_sched_rt_show(struct xnvfile_snapshot_iterator *it,
+                              void *data)
 {
+       struct vfile_sched_rt_data *p = data;
        char pribuf[16], ptbuf[16];
-       struct xnsched_rt_info *p;
 
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq, "%-3s  %-6s %-8s %-10s %s\n",
-                          "CPU", "PID", "PRI", "PERIOD", "NAME");
+       if (p == NULL)
+               xnvfile_printf(it, "%-3s  %-6s %-8s %-10s %s\n",
+                              "CPU", "PID", "PRI", "PERIOD", "NAME");
        else {
-               p = v;
-
                if (p->cprio != p->dnprio)
                        snprintf(pribuf, sizeof(pribuf), "%3d(%d)",
                                 p->cprio, p->dnprio);
@@ -221,121 +254,47 @@ static int xnsched_rt_seq_show(struct seq_file *seq, 
void *v)
 
                xntimer_format_time(p->period, p->periodic, ptbuf, 
sizeof(ptbuf));
 
-               seq_printf(seq, "%3u  %-6d %-8s %-10s %s\n",
-                          p->cpu,
-                          p->pid,
-                          pribuf,
-                          ptbuf,
-                          p->name);
+               xnvfile_printf(it, "%3u  %-6d %-8s %-10s %s\n",
+                              p->cpu,
+                              p->pid,
+                              pribuf,
+                              ptbuf,
+                              p->name);
        }
 
        return 0;
 }
 
-static struct seq_operations xnsched_rt_seq_op = {
-       .start = &xnsched_rt_seq_start,
-       .next = &xnsched_rt_seq_next,
-       .stop = &xnsched_rt_seq_stop,
-       .show = &xnsched_rt_seq_show
+static struct xnvfile_snapshot_ops vfile_sched_rt_ops = {
+       .rewind = vfile_sched_rt_rewind,
+       .begin = vfile_sched_rt_begin,
+       .next = vfile_sched_rt_next,
+       .end = vfile_sched_rt_end,
+       .show = vfile_sched_rt_show,
 };
 
-static int xnsched_rt_seq_open(struct inode *inode, struct file *file)
+static int xnsched_rt_init_vfile(struct xnsched_class *schedclass,
+                                struct xnvfile_directory *vfroot)
 {
-       struct xnsched_rt_seq_iterator *iter = NULL;
-       struct xnsched_rt_info *p;
-       struct xnholder *holder;
-       struct xnthread *thread;
-       int ret, count, rev, n;
-       struct seq_file *seq;
-       spl_t s;
+       int ret;
 
-       if (!xnpod_active_p())
-               return -ESRCH;
-
-       xnlock_get_irqsave(&nklock, s);
-
-      restart:
-       rev = nkpod->threadq_rev;
-       count = xnsched_class_rt.nthreads;
-       holder = getheadq(&nkpod->threadq);
-
-       xnlock_put_irqrestore(&nklock, s);
-
-       if (iter)
-               kfree(iter);
-
-       if (count == 0)
-               return -ESRCH;
-
-       iter = kmalloc(sizeof(*iter)
-                      + (count - 1) * sizeof(struct xnsched_rt_info),
-                      GFP_KERNEL);
-       if (iter == NULL)
-               return -ENOMEM;
-
-       ret = seq_open(file, &xnsched_rt_seq_op);
-       if (ret) {
-               kfree(iter);
+       ret = xnvfile_init_dir(schedclass->name, &sched_rt_vfroot, vfroot);
+       if (ret)
                return ret;
-       }
 
-       iter->nentries = 0;
-       iter->start_time = xntbase_get_jiffies(&nktbase);
-
-       while (holder) {
-               xnlock_get_irqsave(&nklock, s);
-
-               if (nkpod->threadq_rev != rev)
-                       goto restart;
-
-               rev = nkpod->threadq_rev;
-               thread = link2thread(holder, glink);
-
-               if (thread->base_class != &xnsched_class_rt)
-                       goto skip;
-
-               n = iter->nentries++;
-               p = iter->sched_info + n;
-               p->cpu = xnsched_cpu(thread->sched);
-               p->pid = xnthread_user_pid(thread);
-               memcpy(p->name, thread->name, sizeof(p->name));
-               p->cprio = thread->cprio;
-               p->dnprio = xnthread_get_denormalized_prio(thread, 
thread->cprio);
-               p->period = xnthread_get_period(thread);
-               p->periodic = xntbase_periodic_p(xnthread_time_base(thread));
-       skip:
-               holder = nextq(&nkpod->threadq, holder);
-               xnlock_put_irqrestore(&nklock, s);
-       }
-
-       seq = file->private_data;
-       seq->private = iter;
-
-       return 0;
-}
-
-static struct file_operations xnsched_rt_seq_operations = {
-       .owner = THIS_MODULE,
-       .open = xnsched_rt_seq_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
-};
-
-void xnsched_rt_init_proc(struct proc_dir_entry *root)
-{
-       rthal_add_proc_seq("threads", &xnsched_rt_seq_operations, 0, root);
+       return xnvfile_init_snapshot("threads", &vfile_sched_rt,
+                                    &sched_rt_vfroot);
 }
 
-void xnsched_rt_cleanup_proc(struct proc_dir_entry *root)
+static void xnsched_rt_cleanup_vfile(struct xnsched_class *schedclass)
 {
-       remove_proc_entry("threads", root);
+       xnvfile_destroy_snapshot(&vfile_sched_rt);
+       xnvfile_destroy_dir(&sched_rt_vfroot);
 }
 
 #endif /* CONFIG_PROC_FS */
 
 struct xnsched_class xnsched_class_rt = {
-
        .sched_init             =       xnsched_rt_init,
        .sched_enqueue          =       xnsched_rt_enqueue,
        .sched_dequeue          =       xnsched_rt_dequeue,
@@ -356,8 +315,8 @@ struct xnsched_class xnsched_class_rt = {
        .sched_resume_rpi       =       NULL,
 #endif
 #ifdef CONFIG_PROC_FS
-       .sched_init_proc        =       xnsched_rt_init_proc,
-       .sched_cleanup_proc     =       xnsched_rt_cleanup_proc,
+       .sched_init_vfile       =       xnsched_rt_init_vfile,
+       .sched_cleanup_vfile    =       xnsched_rt_cleanup_vfile,
 #endif
        .weight                 =       XNSCHED_CLASS_WEIGHT(1),
        .name                   =       "rt"
diff --git a/ksrc/nucleus/sched-sporadic.c b/ksrc/nucleus/sched-sporadic.c
index 0ea14e0..8d4e9a1 100644
--- a/ksrc/nucleus/sched-sporadic.c
+++ b/ksrc/nucleus/sched-sporadic.c
@@ -415,65 +415,102 @@ static void xnsched_sporadic_resume_rpi(struct xnthread 
*thread)
 
 #ifdef CONFIG_PROC_FS
 
-#include <linux/seq_file.h>
-
-struct xnsched_sporadic_seq_iterator {
-       xnticks_t start_time;
-       int nentries;
-       struct xnsched_sporadic_info {
-               int cpu;
-               pid_t pid;
-               char name[XNOBJECT_NAME_LEN];
-               int current_prio;
-               int low_prio;
-               int normal_prio;
-               int periodic;
-               xnticks_t period;
-               xnticks_t timeout;
-               xnticks_t budget;
-       } sched_info[1];
+struct xnvfile_directory sched_sporadic_vfroot;
+
+struct vfile_sched_sporadic_priv {
+       int nrthreads;
+       struct xnholder *curr;
 };
 
-static void *xnsched_sporadic_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       struct xnsched_sporadic_seq_iterator *iter = seq->private;
+struct vfile_sched_sporadic_data {
+       int cpu;
+       pid_t pid;
+       char name[XNOBJECT_NAME_LEN];
+       int current_prio;
+       int low_prio;
+       int normal_prio;
+       int periodic;
+       xnticks_t period;
+       xnticks_t timeout;
+       xnticks_t budget;
+};
+
+static struct xnvfile_snapshot_ops vfile_sched_sporadic_ops;
+
+static struct xnvfile_snapshot vfile_sched_sporadic = {
+       .privsz = sizeof(struct vfile_sched_sporadic_priv),
+       .datasz = sizeof(struct vfile_sched_sporadic_data),
+       .tag = &nkpod_struct.threadlist_tag,
+       .ops = &vfile_sched_sporadic_ops,
+};
 
-       if (*pos > iter->nentries)
-               return NULL;
+static int vfile_sched_sporadic_rewind(struct xnvfile_snapshot_iterator *it)
+{
+       struct vfile_sched_sporadic_priv *priv = 
xnvfile_snapshot_iterator_priv(it);
 
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
+       priv->nrthreads = xnsched_class_sporadic.nthreads;
+       if (priv->nrthreads == 0)
+               return -ESRCH;
+       priv->curr = getheadq(&nkpod->threadq);
 
-       return iter->sched_info + *pos - 1;
+       return 0;
 }
 
-static void *xnsched_sporadic_seq_next(struct seq_file *seq, void *v, loff_t 
*pos)
+static void *vfile_sched_sporadic_begin(struct xnvfile_snapshot_iterator *it)
 {
-       struct xnsched_sporadic_seq_iterator *iter = seq->private;
-
-       ++*pos;
+       struct vfile_sched_sporadic_priv *priv = 
xnvfile_snapshot_iterator_priv(it);
 
-       if (*pos > iter->nentries)
-               return NULL;
+       return kmalloc(priv->nrthreads * sizeof(struct 
vfile_sched_sporadic_data),
+                      GFP_KERNEL);
+}
 
-       return iter->sched_info + *pos - 1;
+static void vfile_sched_sporadic_end(struct xnvfile_snapshot_iterator *it,
+                              void *buf)
+{
+       kfree(buf);
 }
 
-static void xnsched_sporadic_seq_stop(struct seq_file *seq, void *v)
+static int vfile_sched_sporadic_next(struct xnvfile_snapshot_iterator *it,
+                                    void *data)
 {
+       struct vfile_sched_sporadic_priv *priv = 
xnvfile_snapshot_iterator_priv(it);
+       struct vfile_sched_sporadic_data *p = data;
+       struct xnthread *thread;
+
+       if (priv->curr == NULL)
+               return 0;       /* All done. */
+
+       thread = link2thread(priv->curr, glink);
+       priv->curr = nextq(&nkpod->threadq, priv->curr);
+
+       if (thread->base_class != &xnsched_class_sporadic)
+               return VFILE_SEQ_SKIP;
+
+       p->cpu = xnsched_cpu(thread->sched);
+       p->pid = xnthread_user_pid(thread);
+       memcpy(p->name, thread->name, sizeof(p->name));
+       p->current_prio = thread->cprio;
+       p->low_prio = thread->pss->param.low_prio;
+       p->normal_prio = thread->pss->param.normal_prio;
+       p->period = xnthread_get_period(thread);
+       p->budget = thread->pss->param.init_budget;
+       p->periodic = xntbase_periodic_p(xnthread_time_base(thread));
+
+       return 1;
 }
 
-static int xnsched_sporadic_seq_show(struct seq_file *seq, void *v)
+static int vfile_sched_sporadic_show(struct xnvfile_snapshot_iterator *it,
+                                    void *data)
 {
        char lpbuf[16], npbuf[16], ptbuf[16], btbuf[16];
-       struct xnsched_sporadic_info *p;
+       struct vfile_sched_sporadic_data *p = data;
 
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq, "%-3s  %-6s %-4s %-4s  %-10s %-10s %s\n",
-                          "CPU", "PID", "LPRI", "NPRI", "BUDGET", "PERIOD", 
"NAME");
+       if (p == NULL)
+               xnvfile_printf(it,
+                              "%-3s  %-6s %-4s %-4s  %-10s %-10s %s\n",
+                              "CPU", "PID", "LPRI", "NPRI", "BUDGET",
+                              "PERIOD", "NAME");
        else {
-               p = v;
-
                snprintf(lpbuf, sizeof(lpbuf), "%3d%c",
                         p->low_prio, p->current_prio == p->low_prio ? '*' : ' 
');
 
@@ -483,125 +520,51 @@ static int xnsched_sporadic_seq_show(struct seq_file 
*seq, void *v)
                xntimer_format_time(p->period, p->periodic, ptbuf, 
sizeof(ptbuf));
                xntimer_format_time(p->budget, p->periodic, btbuf, 
sizeof(btbuf));
 
-               seq_printf(seq, "%3u  %-6d %-4s %-4s  %-10s %-10s %s\n",
-                          p->cpu,
-                          p->pid,
-                          lpbuf,
-                          npbuf,
-                          btbuf,
-                          ptbuf,
-                          p->name);
+               xnvfile_printf(it,
+                              "%3u  %-6d %-4s %-4s  %-10s %-10s %s\n",
+                              p->cpu,
+                              p->pid,
+                              lpbuf,
+                              npbuf,
+                              btbuf,
+                              ptbuf,
+                              p->name);
        }
 
        return 0;
 }
 
-static struct seq_operations xnsched_sporadic_seq_op = {
-       .start = &xnsched_sporadic_seq_start,
-       .next = &xnsched_sporadic_seq_next,
-       .stop = &xnsched_sporadic_seq_stop,
-       .show = &xnsched_sporadic_seq_show
+static struct xnvfile_snapshot_ops vfile_sched_sporadic_ops = {
+       .rewind = vfile_sched_sporadic_rewind,
+       .begin = vfile_sched_sporadic_begin,
+       .next = vfile_sched_sporadic_next,
+       .end = vfile_sched_sporadic_end,
+       .show = vfile_sched_sporadic_show,
 };
 
-static int xnsched_sporadic_seq_open(struct inode *inode, struct file *file)
+static int xnsched_sporadic_init_vfile(struct xnsched_class *schedclass,
+                                      struct xnvfile_directory *vfroot)
 {
-       struct xnsched_sporadic_seq_iterator *iter = NULL;
-       struct xnsched_sporadic_info *p;
-       struct xnholder *holder;
-       struct xnthread *thread;
-       int ret, count, rev, n;
-       struct seq_file *seq;
-       spl_t s;
-
-       if (!xnpod_active_p())
-               return -ESRCH;
-
-       xnlock_get_irqsave(&nklock, s);
-
-      restart:
-       rev = nkpod->threadq_rev;
-       count = xnsched_class_sporadic.nthreads;
-       holder = getheadq(&nkpod->threadq);
-
-       xnlock_put_irqrestore(&nklock, s);
-
-       if (iter)
-               kfree(iter);
-
-       if (count == 0)
-               return -ESRCH;
-
-       iter = kmalloc(sizeof(*iter)
-                      + (count - 1) * sizeof(struct xnsched_sporadic_info),
-                      GFP_KERNEL);
-       if (iter == NULL)
-               return -ENOMEM;
+       int ret;
 
-       ret = seq_open(file, &xnsched_sporadic_seq_op);
-       if (ret) {
-               kfree(iter);
+       ret = xnvfile_init_dir(schedclass->name,
+                              &sched_sporadic_vfroot, vfroot);
+       if (ret)
                return ret;
-       }
-
-       iter->nentries = 0;
-       iter->start_time = xntbase_get_jiffies(&nktbase);
-
-       while (holder) {
-               xnlock_get_irqsave(&nklock, s);
-
-               if (nkpod->threadq_rev != rev)
-                       goto restart;
-
-               rev = nkpod->threadq_rev;
-               thread = link2thread(holder, glink);
-
-               if (thread->base_class != &xnsched_class_sporadic)
-                       goto skip;
-
-               n = iter->nentries++;
-               p = iter->sched_info + n;
-               p->cpu = xnsched_cpu(thread->sched);
-               p->pid = xnthread_user_pid(thread);
-               memcpy(p->name, thread->name, sizeof(p->name));
-               p->current_prio = thread->cprio;
-               p->low_prio = thread->pss->param.low_prio;
-               p->normal_prio = thread->pss->param.normal_prio;
-               p->period = xnthread_get_period(thread);
-               p->budget = thread->pss->param.init_budget;
-               p->periodic = xntbase_periodic_p(xnthread_time_base(thread));
-       skip:
-               holder = nextq(&nkpod->threadq, holder);
-               xnlock_put_irqrestore(&nklock, s);
-       }
 
-       seq = file->private_data;
-       seq->private = iter;
-
-       return 0;
+       return xnvfile_init_snapshot("threads", &vfile_sched_sporadic,
+                                    &sched_sporadic_vfroot);
 }
 
-static struct file_operations xnsched_sporadic_seq_operations = {
-       .owner = THIS_MODULE,
-       .open = xnsched_sporadic_seq_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
-};
-
-void xnsched_sporadic_init_proc(struct proc_dir_entry *root)
+static void xnsched_sporadic_cleanup_vfile(struct xnsched_class *schedclass)
 {
-       rthal_add_proc_seq("threads", &xnsched_sporadic_seq_operations, 0, 
root);
-}
-
-void xnsched_sporadic_cleanup_proc(struct proc_dir_entry *root)
-{
-       remove_proc_entry("threads", root);
+       xnvfile_destroy_snapshot(&vfile_sched_sporadic);
+       xnvfile_destroy_dir(&sched_sporadic_vfroot);
 }
 
 #endif /* CONFIG_PROC_FS */
 
 struct xnsched_class xnsched_class_sporadic = {
-
        .sched_init             =       xnsched_sporadic_init,
        .sched_enqueue          =       xnsched_sporadic_enqueue,
        .sched_dequeue          =       xnsched_sporadic_dequeue,
@@ -623,8 +586,8 @@ struct xnsched_class xnsched_class_sporadic = {
        .sched_resume_rpi       =       xnsched_sporadic_resume_rpi,
 #endif
 #ifdef CONFIG_PROC_FS
-       .sched_init_proc        =       xnsched_sporadic_init_proc,
-       .sched_cleanup_proc     =       xnsched_sporadic_cleanup_proc,
+       .sched_init_vfile       =       xnsched_sporadic_init_vfile,
+       .sched_cleanup_vfile    =       xnsched_sporadic_cleanup_vfile,
 #endif
        .weight                 =       XNSCHED_CLASS_WEIGHT(1),
        .name                   =       "pss"
diff --git a/ksrc/nucleus/sched-tp.c b/ksrc/nucleus/sched-tp.c
index a08b360..070368e 100644
--- a/ksrc/nucleus/sched-tp.c
+++ b/ksrc/nucleus/sched-tp.c
@@ -279,172 +279,129 @@ EXPORT_SYMBOL_GPL(xnsched_tp_get_partition);
 
 #ifdef CONFIG_PROC_FS
 
-#include <linux/seq_file.h>
-
-struct xnsched_tp_seq_iterator {
-       xnticks_t start_time;
-       int nentries;
-       struct xnsched_tp_info {
-               int cpu;
-               pid_t pid;
-               char name[XNOBJECT_NAME_LEN];
-               int prio;
-               int ptid;
-       } sched_info[1];
+struct xnvfile_directory sched_tp_vfroot;
+
+struct vfile_sched_tp_priv {
+       int nrthreads;
+       struct xnholder *curr;
 };
 
-static void *xnsched_tp_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       struct xnsched_tp_seq_iterator *iter = seq->private;
 
-       if (*pos > iter->nentries)
-               return NULL;
+struct vfile_sched_tp_data {
+       int cpu;
+       pid_t pid;
+       char name[XNOBJECT_NAME_LEN];
+       int prio;
+       int ptid;
+};
 
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
+static struct xnvfile_snapshot_ops vfile_sched_tp_ops;
 
-       return iter->sched_info + *pos - 1;
-}
+static struct xnvfile_snapshot vfile_sched_tp = {
+       .privsz = sizeof(struct vfile_sched_tp_priv),
+       .datasz = sizeof(struct vfile_sched_tp_data),
+       .tag = &nkpod_struct.threadlist_tag,
+       .ops = &vfile_sched_tp_ops,
+};
 
-static void *xnsched_tp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static int vfile_sched_tp_rewind(struct xnvfile_snapshot_iterator *it)
 {
-       struct xnsched_tp_seq_iterator *iter = seq->private;
-
-       ++*pos;
+       struct vfile_sched_tp_priv *priv = xnvfile_snapshot_iterator_priv(it);
 
-       if (*pos > iter->nentries)
-               return NULL;
+       priv->nrthreads = xnsched_class_tp.nthreads;
+       priv->curr = getheadq(&nkpod->threadq);
 
-       return iter->sched_info + *pos - 1;
+       return 0;
 }
 
-static void xnsched_tp_seq_stop(struct seq_file *seq, void *v)
+static void *vfile_sched_tp_begin(struct xnvfile_snapshot_iterator *it)
 {
+       struct vfile_sched_tp_priv *priv = xnvfile_snapshot_iterator_priv(it);
+
+       return kmalloc(priv->nrthreads * sizeof(struct vfile_sched_tp_data),
+                      GFP_KERNEL);
 }
 
-static int xnsched_tp_seq_show(struct seq_file *seq, void *v)
+static void vfile_sched_tp_end(struct xnvfile_snapshot_iterator *it,
+                              void *buf)
 {
-       struct xnsched_tp_info *p;
-
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq, "%-3s  %-6s %-4s %-4s  %s\n",
-                          "CPU", "PID", "PTID", "PRI", "NAME");
-       else {
-               p = v;
-
-               seq_printf(seq, "%3u  %-6d %-4d %-4d  %s\n",
-                          p->cpu,
-                          p->pid,
-                          p->ptid,
-                          p->prio,
-                          p->name);
-       }
-
-       return 0;
+       kfree(buf);
 }
 
-static struct seq_operations xnsched_tp_seq_op = {
-       .start = &xnsched_tp_seq_start,
-       .next = &xnsched_tp_seq_next,
-       .stop = &xnsched_tp_seq_stop,
-       .show = &xnsched_tp_seq_show
-};
-
-static int xnsched_tp_seq_open(struct inode *inode, struct file *file)
+static int vfile_sched_tp_next(struct xnvfile_snapshot_iterator *it,
+                              void *data)
 {
-       struct xnsched_tp_seq_iterator *iter = NULL;
-       struct xnsched_tp_info *p;
-       struct xnholder *holder;
+       struct vfile_sched_tp_priv *priv = xnvfile_snapshot_iterator_priv(it);
+       struct vfile_sched_tp_data *p = data;
        struct xnthread *thread;
-       int ret, count, rev, n;
-       struct seq_file *seq;
-       spl_t s;
-
-       if (!xnpod_active_p())
-               return -ESRCH;
-
-       xnlock_get_irqsave(&nklock, s);
 
-      restart:
-       rev = nkpod->threadq_rev;
-       count = xnsched_class_tp.nthreads;
-       holder = getheadq(&nkpod->threadq);
+       if (priv->curr == NULL)
+               return 0;       /* All done. */
 
-       xnlock_put_irqrestore(&nklock, s);
+       thread = link2thread(priv->curr, glink);
+       priv->curr = nextq(&nkpod->threadq, priv->curr);
 
-       if (iter)
-               kfree(iter);
+       if (thread->base_class != &xnsched_class_tp)
+               return VFILE_SEQ_SKIP;
 
-       if (count == 0)
-               return -ESRCH;
+       p->cpu = xnsched_cpu(thread->sched);
+       p->pid = xnthread_user_pid(thread);
+       memcpy(p->name, thread->name, sizeof(p->name));
+       p->ptid = thread->tps - thread->sched->tp.partitions;
+       p->prio = thread->cprio;
 
-       iter = kmalloc(sizeof(*iter)
-                      + (count - 1) * sizeof(struct xnsched_tp_info),
-                      GFP_KERNEL);
-       if (iter == NULL)
-               return -ENOMEM;
-
-       ret = seq_open(file, &xnsched_tp_seq_op);
-       if (ret) {
-               kfree(iter);
-               return ret;
-       }
-
-       iter->nentries = 0;
-       iter->start_time = xntbase_get_jiffies(&nktbase);
-
-       while (holder) {
-               xnlock_get_irqsave(&nklock, s);
-
-               if (nkpod->threadq_rev != rev)
-                       goto restart;
-
-               rev = nkpod->threadq_rev;
-               thread = link2thread(holder, glink);
-
-               if (thread->base_class != &xnsched_class_tp)
-                       goto skip;
-
-               n = iter->nentries++;
-               p = iter->sched_info + n;
-               p->cpu = xnsched_cpu(thread->sched);
-               p->pid = xnthread_user_pid(thread);
-               memcpy(p->name, thread->name, sizeof(p->name));
-               p->ptid = thread->tps - thread->sched->tp.partitions;
-               p->prio = thread->cprio;
-       skip:
-               holder = nextq(&nkpod->threadq, holder);
-               xnlock_put_irqrestore(&nklock, s);
-       }
+       return 1;
+}
 
-       seq = file->private_data;
-       seq->private = iter;
+static int vfile_sched_tp_show(struct xnvfile_snapshot_iterator *it,
+                              void *data)
+{
+       struct vfile_sched_tp_data *p = data;
+
+       if (p == NULL)
+               xnvfile_printf(it, "%-3s  %-6s %-4s %-4s  %s\n",
+                              "CPU", "PID", "PTID", "PRI", "NAME");
+       else
+               xnvfile_printf(it, "%3u  %-6d %-4d %-4d  %s\n",
+                              p->cpu,
+                              p->pid,
+                              p->ptid,
+                              p->prio,
+                              p->name);
 
        return 0;
 }
 
-static struct file_operations xnsched_tp_seq_operations = {
-       .owner = THIS_MODULE,
-       .open = xnsched_tp_seq_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
+static struct xnvfile_snapshot_ops vfile_sched_tp_ops = {
+       .rewind = vfile_sched_tp_rewind,
+       .begin = vfile_sched_tp_begin,
+       .next = vfile_sched_tp_next,
+       .end = vfile_sched_tp_end,
+       .show = vfile_sched_tp_show,
 };
 
-void xnsched_tp_init_proc(struct proc_dir_entry *root)
+static int xnsched_tp_init_vfile(struct xnsched_class *schedclass,
+                                struct xnvfile_directory *vfroot)
 {
-       rthal_add_proc_seq("threads", &xnsched_tp_seq_operations, 0, root);
+       int ret;
+
+       ret = xnvfile_init_dir(schedclass->name, &sched_tp_vfroot, vfroot);
+       if (ret)
+               return ret;
+
+       return xnvfile_init_snapshot("threads", &vfile_sched_tp,
+                                    &sched_tp_vfroot);
 }
 
-void xnsched_tp_cleanup_proc(struct proc_dir_entry *root)
+static void xnsched_tp_cleanup_vfile(struct xnsched_class *schedclass)
 {
-       remove_proc_entry("threads", root);
+       xnvfile_destroy_snapshot(&vfile_sched_tp);
+       xnvfile_destroy_dir(&sched_tp_vfroot);
 }
 
 #endif /* CONFIG_PROC_FS */
 
 struct xnsched_class xnsched_class_tp = {
-
        .sched_init             =       xnsched_tp_init,
        .sched_enqueue          =       xnsched_tp_enqueue,
        .sched_dequeue          =       xnsched_tp_dequeue,
@@ -459,8 +416,8 @@ struct xnsched_class xnsched_class_tp = {
        .sched_declare          =       xnsched_tp_declare,
        .sched_forget           =       xnsched_tp_forget,
 #ifdef CONFIG_PROC_FS
-       .sched_init_proc        =       xnsched_tp_init_proc,
-       .sched_cleanup_proc     =       xnsched_tp_cleanup_proc,
+       .sched_init_vfile       =       xnsched_tp_init_vfile,
+       .sched_cleanup_vfile    =       xnsched_tp_cleanup_vfile,
 #endif
        .weight                 =       XNSCHED_CLASS_WEIGHT(2),
        .name                   =       "tp"
diff --git a/ksrc/nucleus/sched.c b/ksrc/nucleus/sched.c
index 0b737a3..424d5db 100644
--- a/ksrc/nucleus/sched.c
+++ b/ksrc/nucleus/sched.c
@@ -686,66 +686,115 @@ struct xnpholder *nextmlq(struct xnsched_mlq *q, struct 
xnpholder *h)
 
 #ifdef CONFIG_PROC_FS
 
-#include <linux/seq_file.h>
+static struct xnvfile_directory schedclass_vfroot;
 
-static struct proc_dir_entry *schedclass_proc_root;
-
-struct sched_seq_iterator {
+struct vfile_sched_priv {
+       int nrthreads;
+       struct xnholder *curr;
        xnticks_t start_time;
-       int nentries;
-       struct sched_seq_info {
-               int cpu;
-               pid_t pid;
-               char name[XNOBJECT_NAME_LEN];
-               char timebase[XNOBJECT_NAME_LEN];
-               char sched_class[XNOBJECT_NAME_LEN];
-               int cprio;
-               int dnprio;
-               int periodic;
-               xnticks_t timeout;
-               xnflags_t state;
-       } sched_info[1];
 };
 
-static void *sched_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       struct sched_seq_iterator *iter = seq->private;
+struct vfile_sched_data {
+       int cpu;
+       pid_t pid;
+       char name[XNOBJECT_NAME_LEN];
+       char timebase[XNOBJECT_NAME_LEN];
+       char sched_class[XNOBJECT_NAME_LEN];
+       int cprio;
+       int dnprio;
+       int periodic;
+       xnticks_t timeout;
+       xnflags_t state;
+};
 
-       if (*pos > iter->nentries)
-               return NULL;
+static struct xnvfile_snapshot_ops vfile_sched_ops;
 
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
+static struct xnvfile_snapshot sched_vfile = {
+       .privsz = sizeof(struct vfile_sched_priv),
+       .datasz = sizeof(struct vfile_sched_data),
+       .tag = &nkpod_struct.threadlist_tag,
+       .ops = &vfile_sched_ops,
+};
+
+static int vfile_sched_rewind(struct xnvfile_snapshot_iterator *it)
+{
+       struct vfile_sched_priv *priv = xnvfile_snapshot_iterator_priv(it);
 
-       return iter->sched_info + *pos - 1;
+       priv->nrthreads = countq(&nkpod->threadq);
+       priv->curr = getheadq(&nkpod->threadq);
+       priv->start_time = xntbase_get_jiffies(&nktbase);
+
+       return 0;
 }
 
-static void *sched_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *vfile_sched_begin(struct xnvfile_snapshot_iterator *it)
 {
-       struct sched_seq_iterator *iter = seq->private;
-
-       ++*pos;
+       struct vfile_sched_priv *priv = xnvfile_snapshot_iterator_priv(it);
 
-       if (*pos > iter->nentries)
-               return NULL;
+       return kmalloc(priv->nrthreads * sizeof(struct vfile_sched_data),
+                      GFP_KERNEL);
+}
 
-       return iter->sched_info + *pos - 1;
+static void vfile_sched_end(struct xnvfile_snapshot_iterator *it, void *buf)
+{
+       kfree(buf);
 }
 
-static void sched_seq_stop(struct seq_file *seq, void *v)
+static int vfile_sched_next(struct xnvfile_snapshot_iterator *it, void *data)
 {
+       struct vfile_sched_priv *priv = xnvfile_snapshot_iterator_priv(it);
+       struct vfile_sched_data *p = data;
+       xnticks_t timeout, period;
+       struct xnthread *thread;
+
+       if (priv->curr == NULL)
+               return 0;       /* All done. */
+
+       thread = link2thread(priv->curr, glink);
+       priv->curr = nextq(&nkpod->threadq, priv->curr);
+
+       p->cpu = xnsched_cpu(thread->sched);
+       p->pid = xnthread_user_pid(thread);
+       memcpy(p->name, thread->name, sizeof(p->name));
+       p->cprio = thread->cprio;
+       p->dnprio = xnthread_get_denormalized_prio(thread, thread->cprio);
+       p->state = xnthread_state_flags(thread);
+       memcpy(p->timebase, xntbase_name(xnthread_time_base(thread)),
+              sizeof(p->timebase));
+       xnobject_copy_name(p->sched_class, thread->sched_class->name);
+       period = xnthread_get_period(thread);
+       timeout = xnthread_get_timeout(thread, priv->start_time);
+       /*
+        * Here we cheat: thread is periodic and the sampling rate may
+        * be high, so it is indeed possible that the next tick date
+        * from the ptimer progresses fast enough while we are busy
+        * collecting output data in this loop, so that next_date -
+        * start_time > period. In such a case, we simply ceil the
+        * value to period to keep the result meaningful, even if not
+        * necessarily accurate. But what does accuracy mean when the
+        * sampling frequency is high, and the way to read it has to
+        * go through the vfile interface anyway?
+        */
+       if (period > 0 && period < timeout &&
+           !xntimer_running_p(&thread->rtimer))
+               timeout = period;
+       p->timeout = timeout;
+       p->periodic = xntbase_periodic_p(xnthread_time_base(thread));
+
+       return 1;
 }
 
-static int sched_seq_show(struct seq_file *seq, void *v)
+static int vfile_sched_show(struct xnvfile_snapshot_iterator *it, void *data)
 {
+       struct vfile_sched_data *p = data;
        char sbuf[64], pbuf[16], tbuf[16];
 
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq, "%-3s  %-6s %-5s  %-8s %-8s  %-10s %-10s %s\n",
-                          "CPU", "PID", "CLASS", "PRI", "TIMEOUT", "TIMEBASE", 
"STAT", "NAME");
+       if (p == NULL)
+               xnvfile_printf(it,
+                              "%-3s  %-6s %-5s  %-8s %-8s  %-10s %-10s %s\n",
+                              "CPU", "PID", "CLASS", "PRI", "TIMEOUT",
+                              "TIMEBASE", "STAT", "NAME");
        else {
-               struct sched_seq_info *p = v;
-
                if (p->cprio != p->dnprio)
                        snprintf(pbuf, sizeof(pbuf), "%3d(%d)",
                                 p->cprio, p->dnprio);
@@ -755,419 +804,272 @@ static int sched_seq_show(struct seq_file *seq, void *v)
                xntimer_format_time(p->timeout, p->periodic, tbuf, 
sizeof(tbuf));
                xnthread_format_status(p->state, sbuf, sizeof(sbuf));
 
-               seq_printf(seq, "%3u  %-6d %-5s  %-8s %-8s  %-10s %-10s %s\n",
-                          p->cpu,
-                          p->pid,
-                          p->sched_class,
-                          pbuf,
-                          tbuf,
-                          p->timebase,
-                          sbuf,
-                          p->name);
+               xnvfile_printf(it,
+                              "%3u  %-6d %-5s  %-8s %-8s  %-10s %-10s %s\n",
+                              p->cpu,
+                              p->pid,
+                              p->sched_class,
+                              pbuf,
+                              tbuf,
+                              p->timebase,
+                              sbuf,
+                              p->name);
        }
 
        return 0;
 }
 
-static struct seq_operations sched_op = {
-       .start = &sched_seq_start,
-       .next = &sched_seq_next,
-       .stop = &sched_seq_stop,
-       .show = &sched_seq_show
+static struct xnvfile_snapshot_ops vfile_sched_ops = {
+       .rewind = vfile_sched_rewind,
+       .begin = vfile_sched_begin,
+       .next = vfile_sched_next,
+       .end = vfile_sched_end,
+       .show = vfile_sched_show,
 };
 
-static int sched_seq_open(struct inode *inode, struct file *file)
-{
-       struct sched_seq_iterator *iter = NULL;
-       xnticks_t period, timeout;
-       struct xnholder *holder;
-       struct sched_seq_info *p;
-       struct seq_file *seq;
-       int err, count, rev;
-       spl_t s;
-
-       if (!xnpod_active_p())
-               return -ESRCH;
-
-       xnlock_get_irqsave(&nklock, s);
-
-      restart:
-       rev = nkpod->threadq_rev;
-       count = countq(&nkpod->threadq);        /* Cannot be empty (ROOT) */
-       holder = getheadq(&nkpod->threadq);
-
-       xnlock_put_irqrestore(&nklock, s);
-
-       if (iter)
-               kfree(iter);
-       iter = kmalloc(sizeof(*iter)
-                      + (count - 1) * sizeof(struct sched_seq_info),
-                      GFP_KERNEL);
-       if (!iter)
-               return -ENOMEM;
-
-       err = seq_open(file, &sched_op);
-
-       if (err) {
-               kfree(iter);
-               return err;
-       }
-
-       iter->nentries = 0;
-       iter->start_time = xntbase_get_jiffies(&nktbase);
-
-       /*
-        * Take a snapshot element-wise, restart if something changes
-        * underneath us.
-        */
-       while (holder) {
-               xnthread_t *thread;
-               int n;
-
-               xnlock_get_irqsave(&nklock, s);
-
-               if (nkpod->threadq_rev != rev)
-                       goto restart;
-
-               rev = nkpod->threadq_rev;
-               thread = link2thread(holder, glink);
-               n = iter->nentries++;
-               p = iter->sched_info + n;
-
-               p->cpu = xnsched_cpu(thread->sched);
-               p->pid = xnthread_user_pid(thread);
-               memcpy(p->name, thread->name, sizeof(p->name));
-               p->cprio = thread->cprio;
-               p->dnprio = xnthread_get_denormalized_prio(thread, 
thread->cprio);
-               p->state = xnthread_state_flags(thread);
-               memcpy(p->timebase, xntbase_name(xnthread_time_base(thread)),
-                      sizeof(p->timebase));
-               xnobject_copy_name(p->sched_class, thread->sched_class->name);
-               period = xnthread_get_period(thread);
-               timeout = xnthread_get_timeout(thread, iter->start_time);
-               /*
-                * Here we cheat: thread is periodic and the sampling
-                * rate may be high, so it is indeed possible that the
-                * next tick date from the ptimer progresses fast
-                * enough while we are busy collecting output data in
-                * this loop, so that next_date - start_time >
-                * period. In such a case, we simply ceil the value to
-                * period to keep the result meaningful, even if not
-                * necessarily accurate. But what does accuracy mean
-                * when the sampling frequency is high, and the way to
-                * read it has to go through the /proc interface
-                * anyway?
-                */
-               if (period > 0 && period < timeout &&
-                   !xntimer_running_p(&thread->rtimer))
-                       timeout = period;
-               p->timeout = timeout;
-               p->periodic = xntbase_periodic_p(xnthread_time_base(thread));
-
-               holder = nextq(&nkpod->threadq, holder);
-               xnlock_put_irqrestore(&nklock, s);
-       }
-
-       seq = file->private_data;
-       seq->private = iter;
+#ifdef CONFIG_XENO_OPT_STATS
 
-       return 0;
-}
+struct vfile_stat_priv {
+       int nrthreads;
+       int irq;
+       struct xnholder *curr;
+       struct xnintr_iterator intr_it;
+};
 
-static struct file_operations sched_seq_operations = {
-       .owner = THIS_MODULE,
-       .open = sched_seq_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
+struct vfile_stat_data {
+       int cpu;
+       pid_t pid;
+       xnflags_t state;
+       char name[XNOBJECT_NAME_LEN];
+       unsigned long ssw;
+       unsigned long csw;
+       unsigned long pf;
+       xnticks_t exectime_period;
+       xnticks_t account_period;
+       xnticks_t exectime_total;
 };
 
-#ifdef CONFIG_XENO_OPT_STATS
+static struct xnvfile_snapshot_ops vfile_stat_ops;
 
-struct stat_seq_iterator {
-       int nentries;
-       struct stat_seq_info {
-               int cpu;
-               pid_t pid;
-               xnflags_t state;
-               char name[XNOBJECT_NAME_LEN];
-               unsigned long ssw;
-               unsigned long csw;
-               unsigned long pf;
-               xnticks_t exectime_period;
-               xnticks_t account_period;
-               xnticks_t exectime_total;
-       } stat_info[1];
+static struct xnvfile_snapshot stat_vfile = {
+       .privsz = sizeof(struct vfile_stat_priv),
+       .datasz = sizeof(struct vfile_stat_data),
+       .tag = &nkpod_struct.threadlist_tag,
+       .ops = &vfile_stat_ops,
 };
 
-static void *stat_seq_start(struct seq_file *seq, loff_t *pos)
+static int vfile_stat_rewind(struct xnvfile_snapshot_iterator *it)
 {
-       struct stat_seq_iterator *iter = seq->private;
-
-       if (*pos > iter->nentries)
-               return NULL;
+       struct vfile_stat_priv *priv = xnvfile_snapshot_iterator_priv(it);
 
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
+       priv->nrthreads = countq(&nkpod->threadq);
+       priv->curr = getheadq(&nkpod->threadq);
+       priv->irq = 0;
 
-       return iter->stat_info + *pos - 1;
+       return 0;
 }
 
-static void *stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+static void *vfile_stat_begin(struct xnvfile_snapshot_iterator *it)
 {
-       struct stat_seq_iterator *iter = seq->private;
-
-       ++*pos;
+       struct vfile_stat_priv *priv = xnvfile_snapshot_iterator_priv(it);
+       int intr_count;
 
-       if (*pos > iter->nentries)
-               return NULL;
+       /*
+        * The activity numbers on each valid interrupt descriptor are
+        * grouped under a pseudo-thread.
+        */
+       intr_count = xnintr_query_init(&priv->intr_it);
+       priv->nrthreads += intr_count * XNARCH_NR_CPUS;
 
-       return iter->stat_info + *pos - 1;
+       return kmalloc(priv->nrthreads * sizeof(struct vfile_stat_data),
+                      GFP_KERNEL);
 }
 
-static void stat_seq_stop(struct seq_file *seq, void *v)
+static void vfile_stat_end(struct xnvfile_snapshot_iterator *it, void *buf)
 {
+       kfree(buf);
 }
 
-static int __stat_seq_open(struct inode *inode,
-                          struct file *file, struct seq_operations *ops)
+static int vfile_stat_next(struct xnvfile_snapshot_iterator *it, void *data)
 {
-       struct stat_seq_iterator *iter = NULL;
-       struct stat_seq_info *stat_info;
-       int err, count, thrq_rev, irq;
-       xnintr_iterator_t intr_iter;
-       struct seq_file *seq;
-       xnholder_t *holder;
-       int intr_count;
-       spl_t s;
-
-       if (!xnpod_active_p())
-               return -ESRCH;
-
-      restart_unlocked:
-       xnlock_get_irqsave(&nklock, s);
-
-      restart:
-       count = countq(&nkpod->threadq);        /* Cannot be empty (ROOT) */
-       holder = getheadq(&nkpod->threadq);
-       thrq_rev = nkpod->threadq_rev;
-
-       xnlock_put_irqrestore(&nklock, s);
-
-       intr_count = xnintr_query_init(&intr_iter);
-       count += intr_count * RTHAL_NR_CPUS;
-
-       if (iter)
-               kfree(iter);
-       iter = kmalloc(sizeof(*iter)
-                      + (count - 1) * sizeof(struct stat_seq_info),
-                      GFP_KERNEL);
-       if (!iter)
-               return -ENOMEM;
-
-       err = seq_open(file, ops);
+       struct vfile_stat_priv *priv = xnvfile_snapshot_iterator_priv(it);
+       struct vfile_stat_data *p = data;
+       struct xnthread *thread;
+       struct xnsched *sched;
+       xnticks_t period;
+       int ret;
 
-       if (err) {
-               kfree(iter);
-               return err;
+       if (priv->curr == NULL)
+               /*
+                * We are done with actual threads, scan interrupt
+                * descriptors.
+                */
+               goto scan_irqs;
+
+       thread = link2thread(priv->curr, glink);
+       priv->curr = nextq(&nkpod->threadq, priv->curr);
+
+       sched = thread->sched;
+       p->cpu = xnsched_cpu(sched);
+       p->pid = xnthread_user_pid(thread);
+       memcpy(p->name, thread->name, sizeof(p->name));
+       p->state = xnthread_state_flags(thread);
+       p->ssw = xnstat_counter_get(&thread->stat.ssw);
+       p->csw = xnstat_counter_get(&thread->stat.csw);
+       p->pf = xnstat_counter_get(&thread->stat.pf);
+
+       period = sched->last_account_switch - thread->stat.lastperiod.start;
+       if (period == 0 && thread == sched->curr) {
+               p->exectime_period = 1;
+               p->account_period = 1;
+       } else {
+               p->exectime_period = thread->stat.account.total -
+                       thread->stat.lastperiod.total;
+               p->account_period = period;
        }
+       p->exectime_total = thread->stat.account.total;
+       thread->stat.lastperiod.total = thread->stat.account.total;
+       thread->stat.lastperiod.start = sched->last_account_switch;
 
-       iter->nentries = 0;
-
-       /* Take a snapshot element-wise, restart if something changes
-          underneath us. */
-
-       while (holder) {
-               xnthread_t *thread;
-               xnsched_t *sched;
-               xnticks_t period;
-
-               xnlock_get_irqsave(&nklock, s);
-
-               if (nkpod->threadq_rev != thrq_rev)
-                       goto restart;
-
-               thread = link2thread(holder, glink);
-               stat_info = &iter->stat_info[iter->nentries++];
-
-               sched = thread->sched;
-               stat_info->cpu = xnsched_cpu(sched);
-               stat_info->pid = xnthread_user_pid(thread);
-               memcpy(stat_info->name, thread->name,
-                      sizeof(stat_info->name));
-               stat_info->state = xnthread_state_flags(thread);
-               stat_info->ssw = xnstat_counter_get(&thread->stat.ssw);
-               stat_info->csw = xnstat_counter_get(&thread->stat.csw);
-               stat_info->pf = xnstat_counter_get(&thread->stat.pf);
-
-               period = sched->last_account_switch - 
thread->stat.lastperiod.start;
-               if (!period && thread == sched->curr) {
-                       stat_info->exectime_period = 1;
-                       stat_info->account_period = 1;
-               } else {
-                       stat_info->exectime_period = thread->stat.account.total 
-
-                               thread->stat.lastperiod.total;
-                       stat_info->account_period = period;
-               }
-               stat_info->exectime_total = thread->stat.account.total;
-               thread->stat.lastperiod.total = thread->stat.account.total;
-               thread->stat.lastperiod.start = sched->last_account_switch;
+       return 1;
 
-               holder = nextq(&nkpod->threadq, holder);
+scan_irqs:
+       if (priv->irq >= XNARCH_NR_IRQS)
+               return 0;       /* All done. */
 
-               xnlock_put_irqrestore(&nklock, s);
+       ret = xnintr_query_next(priv->irq++, &priv->intr_it, p->name);
+       if (ret) {
+               if (ret == -EAGAIN)
+                       xnvfile_touch(it->vfile); /* force rewind. */
+               return VFILE_SEQ_SKIP;
        }
 
-       /* Iterate over all IRQ numbers, ... */
-       for (irq = 0; irq < XNARCH_NR_IRQS; irq++)
-               /* ...over all shared IRQs on all CPUs */
-               while (1) {
-                       stat_info = &iter->stat_info[iter->nentries];
-
-                       err = xnintr_query_next(irq, &intr_iter,
-                                               stat_info->name);
-                       if (err) {
-                               if (err == -EAGAIN)
-                                       goto restart_unlocked;
-                               break; /* line unused or end of chain */
-                       }
-
-                       if (xnarch_cpu_supported(intr_iter.cpu)) {
-                               stat_info->cpu = intr_iter.cpu;
-                               stat_info->csw = intr_iter.hits;
-                               stat_info->exectime_period =
-                                       intr_iter.exectime_period;
-                               stat_info->account_period =
-                                       intr_iter.account_period;
-                               stat_info->exectime_total =
-                                       intr_iter.exectime_total;
-                               stat_info->pid = 0;
-                               stat_info->state =  0;
-                               stat_info->ssw = 0;
-                               stat_info->pf = 0;
-
-                               iter->nentries++;
-                       }
-               }
+       if (!xnarch_cpu_supported(priv->intr_it.cpu))
+               return VFILE_SEQ_SKIP;
 
-       seq = file->private_data;
-       seq->private = iter;
+       p->cpu = priv->intr_it.cpu;
+       p->csw = priv->intr_it.hits;
+       p->exectime_period = priv->intr_it.exectime_period;
+       p->account_period = priv->intr_it.account_period;
+       p->exectime_total = priv->intr_it.exectime_total;
+       p->pid = 0;
+       p->state =  0;
+       p->ssw = 0;
+       p->pf = 0;
 
-       return 0;
+       return 1;
 }
 
-static int stat_seq_show(struct seq_file *seq, void *v)
+static int vfile_stat_show(struct xnvfile_snapshot_iterator *it, void *data)
 {
-       if (v == SEQ_START_TOKEN)
-               seq_printf(seq, "%-3s  %-6s %-10s %-10s %-4s  %-8s  %5s"
-                          "  %s\n",
-                          "CPU", "PID", "MSW", "CSW", "PF", "STAT", "%CPU",
-                          "NAME");
+       struct vfile_stat_data *p = data;
+       int usage = 0;
+
+       if (p == NULL)
+               xnvfile_printf(it,
+                              "%-3s  %-6s %-10s %-10s %-4s  %-8s  %5s"
+                              "  %s\n",
+                              "CPU", "PID", "MSW", "CSW", "PF", "STAT", "%CPU",
+                              "NAME");
        else {
-               struct stat_seq_info *p = v;
-               int usage = 0;
-
                if (p->account_period) {
-                       while (p->account_period > 0xFFFFFFFF) {
+                       while (p->account_period > 0xffffffffUL) {
                                p->exectime_period >>= 16;
                                p->account_period >>= 16;
                        }
-                       usage =
-                           xnarch_ulldiv(p->exectime_period * 1000LL +
-                                         (p->account_period >> 1),
-                                         p->account_period, NULL);
+                       usage = xnarch_ulldiv(p->exectime_period * 1000LL +
+                                             (p->account_period >> 1),
+                                             p->account_period, NULL);
                }
-               seq_printf(seq, "%3u  %-6d %-10lu %-10lu %-4lu  %.8lx  %3u.%u"
-                          "  %s\n",
-                          p->cpu, p->pid, p->ssw, p->csw, p->pf, p->state,
-                          usage / 10, usage % 10, p->name);
+               xnvfile_printf(it,
+                              "%3u  %-6d %-10lu %-10lu %-4lu  %.8lx  %3u.%u"
+                              "  %s\n",
+                              p->cpu, p->pid, p->ssw, p->csw, p->pf, p->state,
+                              usage / 10, usage % 10, p->name);
        }
 
        return 0;
 }
 
-static struct seq_operations stat_op = {
-       .start = &stat_seq_start,
-       .next = &stat_seq_next,
-       .stop = &stat_seq_stop,
-       .show = &stat_seq_show
-};
-
-static int stat_seq_open(struct inode *inode, struct file *file)
+static int vfile_acct_show(struct xnvfile_snapshot_iterator *it, void *data)
 {
-       return __stat_seq_open(inode, file, &stat_op);
-}
+       struct vfile_stat_data *p = data;
 
-static struct file_operations stat_seq_operations = {
-       .owner = THIS_MODULE,
-       .open = stat_seq_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
-};
-
-static int acct_seq_show(struct seq_file *seq, void *v)
-{
-       struct stat_seq_info *p;
-
-       if (v == SEQ_START_TOKEN)
+       if (p == NULL)
                return 0;
-       /*
-        * Dump per-thread data.
-        */
-       p = v;
 
-       seq_printf(seq, "%u %d %lu %lu %lu %.8lx %Lu %Lu %Lu %s\n",
-                  p->cpu, p->pid, p->ssw, p->csw, p->pf, p->state,
-                  xnarch_tsc_to_ns(p->account_period), 
xnarch_tsc_to_ns(p->exectime_period),
-                  xnarch_tsc_to_ns(p->exectime_total), p->name);
+       xnvfile_printf(it, "%u %d %lu %lu %lu %.8lx %Lu %Lu %Lu %s\n",
+                      p->cpu, p->pid, p->ssw, p->csw, p->pf, p->state,
+                      xnarch_tsc_to_ns(p->account_period),
+                      xnarch_tsc_to_ns(p->exectime_period),
+                      xnarch_tsc_to_ns(p->exectime_total),
+                      p->name);
 
        return 0;
 }
 
-static struct seq_operations acct_op = {
-       .start = &stat_seq_start,
-       .next = &stat_seq_next,
-       .stop = &stat_seq_stop,
-       .show = &acct_seq_show
+static struct xnvfile_snapshot_ops vfile_stat_ops = {
+       .rewind = vfile_stat_rewind,
+       .begin = vfile_stat_begin,
+       .next = vfile_stat_next,
+       .end = vfile_stat_end,
+       .show = vfile_stat_show,
 };
 
-static int acct_seq_open(struct inode *inode, struct file *file)
-{
-       return __stat_seq_open(inode, file, &acct_op);
-}
+/*
+ * An accounting vfile is a thread statistics vfile in disguise with a
+ * different output format, which is parser-friendly.
+ */
+static struct xnvfile_snapshot_ops vfile_acct_ops;
 
-static struct file_operations acct_seq_operations = {
-       .owner = THIS_MODULE,
-       .open = acct_seq_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
+static struct xnvfile_snapshot acct_vfile = {
+       .privsz = sizeof(struct vfile_stat_priv),
+       .datasz = sizeof(struct vfile_stat_data),
+       .tag = &nkpod_struct.threadlist_tag,
+       .ops = &vfile_acct_ops,
+};
+
+static struct xnvfile_snapshot_ops vfile_acct_ops = {
+       .rewind = vfile_stat_rewind,
+       .begin = vfile_stat_begin,
+       .next = vfile_stat_next,
+       .end = vfile_stat_end,
+       .show = vfile_acct_show,
 };
 
 #endif /* CONFIG_XENO_OPT_STATS */
 
-void xnsched_init_proc(void)
+int xnsched_init_proc(void)
 {
        struct xnsched_class *p;
+       int ret;
 
-       rthal_add_proc_seq("sched", &sched_seq_operations, 0, rthal_proc_root);
-       schedclass_proc_root =
-               create_proc_entry("schedclasses", S_IFDIR, rthal_proc_root);
+       ret = xnvfile_init_snapshot("sched", &sched_vfile, NULL);
+       if (ret)
+               return ret;
+
+       ret = xnvfile_init_dir("schedclasses", &schedclass_vfroot, NULL);
+       if (ret)
+               return ret;
 
        for_each_xnsched_class(p) {
-               if (p->sched_init_proc == NULL)
-                       continue;
-               p->proc = create_proc_entry(p->name, S_IFDIR,
-                                           schedclass_proc_root);
-               if (p->proc)
-                       p->sched_init_proc(p->proc);
+               if (p->sched_init_vfile) {
+                       ret = p->sched_init_vfile(p, &schedclass_vfroot);
+                       if (ret)
+                               return ret;
+               }
        }
 
 #ifdef CONFIG_XENO_OPT_STATS
-       rthal_add_proc_seq("stat", &stat_seq_operations, 0, rthal_proc_root);
-       rthal_add_proc_seq("acct", &acct_seq_operations, 0, rthal_proc_root);
+       ret = xnvfile_init_snapshot("stat", &stat_vfile, NULL);
+       if (ret)
+               return ret;
+       ret = xnvfile_init_snapshot("acct", &acct_vfile, NULL);
+       if (ret)
+               return ret;
 #endif /* CONFIG_XENO_OPT_STATS */
+
+       return 0;
 }
 
 void xnsched_cleanup_proc(void)
@@ -1175,19 +1077,16 @@ void xnsched_cleanup_proc(void)
        struct xnsched_class *p;
 
        for_each_xnsched_class(p) {
-               if (p->proc == NULL)
-                       continue;
-               if (p->sched_cleanup_proc)
-                       p->sched_cleanup_proc(p->proc);
-               remove_proc_entry(p->name, schedclass_proc_root);
+               if (p->sched_cleanup_vfile)
+                       p->sched_cleanup_vfile(p);
        }
 
 #ifdef CONFIG_XENO_OPT_STATS
-       remove_proc_entry("acct", rthal_proc_root);
-       remove_proc_entry("stat", rthal_proc_root);
+       xnvfile_destroy_snapshot(&acct_vfile);
+       xnvfile_destroy_snapshot(&stat_vfile);
 #endif /* CONFIG_XENO_OPT_STATS */
-       remove_proc_entry("schedclasses", rthal_proc_root);
-       remove_proc_entry("sched", rthal_proc_root);
+       xnvfile_destroy_dir(&schedclass_vfroot);
+       xnvfile_destroy_snapshot(&sched_vfile);
 }
 
 #endif /* CONFIG_PROC_FS */


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

Reply via email to