Module: xenomai-rpm Branch: queue/vfile Commit: 21ed7c9f8db791c1c16ff55e6bcc2f887ab585af URL: http://git.xenomai.org/?p=xenomai-rpm.git;a=commit;h=21ed7c9f8db791c1c16ff55e6bcc2f887ab585af
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 | 213 +++++--------- ksrc/nucleus/sched-sporadic.c | 232 ++++++--------- ksrc/nucleus/sched-tp.c | 208 +++++--------- ksrc/nucleus/sched.c | 653 ++++++++++++++++------------------------- 8 files changed, 522 insertions(+), 823 deletions(-) diff --git a/include/nucleus/pod.h b/include/nucleus/pod.h index bab9f07..1ad6014 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..628018a 100644 --- a/ksrc/nucleus/sched-rt.c +++ b/ksrc/nucleus/sched-rt.c @@ -157,62 +157,81 @@ 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 { + struct xnholder *curr; +}; + +struct vfile_sched_rt_data { + int cpu; + pid_t pid; + char name[XNOBJECT_NAME_LEN]; + xnticks_t period; + int periodic; + int cprio; + int dnprio; }; -static void *xnsched_rt_seq_start(struct seq_file *seq, loff_t *pos) +static struct xnvfile_snapshot_ops vfile_sched_rt_ops; + +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 xnsched_rt_seq_iterator *iter = seq->private; + struct vfile_sched_rt_priv *priv = xnvfile_iterator_priv(it); + int nrthreads = xnsched_class_rt.nthreads; - if (*pos > iter->nentries) - return NULL; + if (nrthreads == 0) + return -ESRCH; - if (*pos == 0) - return SEQ_START_TOKEN; + priv->curr = getheadq(&nkpod->threadq); - return iter->sched_info + *pos - 1; + return nrthreads; } -static void *xnsched_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static int vfile_sched_rt_next(struct xnvfile_snapshot_iterator *it, + void *data) { - struct xnsched_rt_seq_iterator *iter = seq->private; + struct vfile_sched_rt_priv *priv = xnvfile_iterator_priv(it); + struct vfile_sched_rt_data *p = data; + struct xnthread *thread; - ++*pos; + if (priv->curr == NULL) + return 0; /* All done. */ - if (*pos > iter->nentries) - return NULL; + thread = link2thread(priv->curr, glink); + priv->curr = nextq(&nkpod->threadq, priv->curr); - return iter->sched_info + *pos - 1; -} + if (thread->base_class != &xnsched_class_rt) + return VFILE_SEQ_SKIP; -static void xnsched_rt_seq_stop(struct seq_file *seq, void *v) -{ + 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 +240,45 @@ 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, + .next = vfile_sched_rt_next, + .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; - - 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); + int ret; - 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 +299,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..3261a8d 100644 --- a/ksrc/nucleus/sched-sporadic.c +++ b/ksrc/nucleus/sched-sporadic.c @@ -415,65 +415,89 @@ 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 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, +}; + +static int vfile_sched_sporadic_rewind(struct xnvfile_snapshot_iterator *it) { - struct xnsched_sporadic_seq_iterator *iter = seq->private; + struct vfile_sched_sporadic_priv *priv = xnvfile_iterator_priv(it); + int nrthreads = xnsched_class_sporadic.nthreads; - if (*pos > iter->nentries) - return NULL; + if (nrthreads == 0) + return -ESRCH; - if (*pos == 0) - return SEQ_START_TOKEN; + priv->curr = getheadq(&nkpod->threadq); - return iter->sched_info + *pos - 1; + return nrthreads; } -static void *xnsched_sporadic_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static int vfile_sched_sporadic_next(struct xnvfile_snapshot_iterator *it, + void *data) { - struct xnsched_sporadic_seq_iterator *iter = seq->private; + struct vfile_sched_sporadic_priv *priv = xnvfile_iterator_priv(it); + struct vfile_sched_sporadic_data *p = data; + struct xnthread *thread; - ++*pos; + if (priv->curr == NULL) + return 0; /* All done. */ - if (*pos > iter->nentries) - return NULL; + thread = link2thread(priv->curr, glink); + priv->curr = nextq(&nkpod->threadq, priv->curr); - return iter->sched_info + *pos - 1; -} + if (thread->base_class != &xnsched_class_sporadic) + return VFILE_SEQ_SKIP; -static void xnsched_sporadic_seq_stop(struct seq_file *seq, void *v) -{ + 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 +507,49 @@ 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, + .next = vfile_sched_sporadic_next, + .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 +571,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..752d094 100644 --- a/ksrc/nucleus/sched-tp.c +++ b/ksrc/nucleus/sched-tp.c @@ -279,172 +279,112 @@ 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]; -}; - -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 xnvfile_directory sched_tp_vfroot; - if (*pos == 0) - return SEQ_START_TOKEN; +struct vfile_sched_tp_priv { + struct xnholder *curr; +}; - return iter->sched_info + *pos - 1; -} -static void *xnsched_tp_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - struct xnsched_tp_seq_iterator *iter = seq->private; +struct vfile_sched_tp_data { + int cpu; + pid_t pid; + char name[XNOBJECT_NAME_LEN]; + int prio; + int ptid; +}; - ++*pos; +static struct xnvfile_snapshot_ops vfile_sched_tp_ops; - if (*pos > iter->nentries) - return NULL; - - 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_stop(struct seq_file *seq, void *v) +static int vfile_sched_tp_rewind(struct xnvfile_snapshot_iterator *it) { -} + struct vfile_sched_tp_priv *priv = xnvfile_iterator_priv(it); + int nrthreads = xnsched_class_tp.nthreads; -static int xnsched_tp_seq_show(struct seq_file *seq, void *v) -{ - 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); - } + priv->curr = getheadq(&nkpod->threadq); - return 0; + return nrthreads; } -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_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; + if (priv->curr == NULL) + return 0; /* All done. */ - xnlock_get_irqsave(&nklock, s); + thread = link2thread(priv->curr, glink); + priv->curr = nextq(&nkpod->threadq, priv->curr); - restart: - rev = nkpod->threadq_rev; - count = xnsched_class_tp.nthreads; - holder = getheadq(&nkpod->threadq); + if (thread->base_class != &xnsched_class_tp) + return VFILE_SEQ_SKIP; - xnlock_put_irqrestore(&nklock, s); + 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; - if (iter) - kfree(iter); - - if (count == 0) - return -ESRCH; - - 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, + .next = vfile_sched_tp_next, + .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 +399,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 0b51882..3e49086 100644 --- a/ksrc/nucleus/sched.c +++ b/ksrc/nucleus/sched.c @@ -687,66 +687,100 @@ 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 { + 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; - - if (*pos > iter->nentries) - return NULL; +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 == 0) - return SEQ_START_TOKEN; +static struct xnvfile_snapshot_ops vfile_sched_ops; - return iter->sched_info + *pos - 1; -} +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 void *sched_seq_next(struct seq_file *seq, void *v, loff_t *pos) +static int vfile_sched_rewind(struct xnvfile_snapshot_iterator *it) { - struct sched_seq_iterator *iter = seq->private; + struct vfile_sched_priv *priv = xnvfile_iterator_priv(it); - ++*pos; + priv->curr = getheadq(&nkpod->threadq); + priv->start_time = xntbase_get_jiffies(&nktbase); - if (*pos > iter->nentries) - return NULL; - - return iter->sched_info + *pos - 1; + return countq(&nkpod->threadq); } -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_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); @@ -756,419 +790,249 @@ 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 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; - - return 0; -} - -static struct file_operations sched_seq_operations = { - .owner = THIS_MODULE, - .open = sched_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, +static struct xnvfile_snapshot_ops vfile_sched_ops = { + .rewind = vfile_sched_rewind, + .next = vfile_sched_next, + .show = vfile_sched_show, }; #ifdef CONFIG_XENO_OPT_STATS -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]; +struct vfile_stat_priv { + int irq; + struct xnholder *curr; + struct xnintr_iterator intr_it; }; -static void *stat_seq_start(struct seq_file *seq, loff_t *pos) -{ - struct stat_seq_iterator *iter = seq->private; - - if (*pos > iter->nentries) - return NULL; +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; +}; - if (*pos == 0) - return SEQ_START_TOKEN; +static struct xnvfile_snapshot_ops vfile_stat_ops; - return iter->stat_info + *pos - 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_next(struct seq_file *seq, void *v, loff_t *pos) +static int vfile_stat_rewind(struct xnvfile_snapshot_iterator *it) { - struct stat_seq_iterator *iter = seq->private; - - ++*pos; + struct vfile_stat_priv *priv = xnvfile_iterator_priv(it); + int irqnr; - if (*pos > iter->nentries) - return NULL; - - return iter->stat_info + *pos - 1; -} + /* + * The activity numbers on each valid interrupt descriptor are + * grouped under a pseudo-thread. + */ + priv->curr = getheadq(&nkpod->threadq); + priv->irq = 0; + irqnr = xnintr_query_init(&priv->intr_it) * XNARCH_NR_CPUS; -static void stat_seq_stop(struct seq_file *seq, void *v) -{ + return irqnr + countq(&nkpod->threadq); } -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_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) -{ - return __stat_seq_open(inode, file, &stat_op); -} - -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) +static int vfile_acct_show(struct xnvfile_snapshot_iterator *it, void *data) { - struct stat_seq_info *p; + struct vfile_stat_data *p = data; - 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, + .next = vfile_stat_next, + .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, + .next = vfile_stat_next, + .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) @@ -1176,19 +1040,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