diff options
Diffstat (limited to 'misc-modules')
-rw-r--r-- | misc-modules/jiq.c | 125 |
1 files changed, 75 insertions, 50 deletions
diff --git a/misc-modules/jiq.c b/misc-modules/jiq.c index 8b5638f..adc4d33 100644 --- a/misc-modules/jiq.c +++ b/misc-modules/jiq.c @@ -23,6 +23,7 @@ #include <linux/kernel.h> #include <linux/fs.h> /* everything... */ #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/errno.h> /* error codes */ #include <linux/workqueue.h> #include <linux/preempt.h> @@ -36,7 +37,6 @@ MODULE_LICENSE("Dual BSD/GPL"); static long delay = 1; module_param(delay, long, 0); - /* * This module is a silly one: it only embeds short code fragments * that show how enqueued tasks `feel' the environment @@ -57,20 +57,17 @@ static DECLARE_WAIT_QUEUE_HEAD (jiq_wait); static struct clientdata { struct work_struct jiq_work; struct delayed_work jiq_delayed_work; + struct seq_file *m; int len; - char *buf; unsigned long jiffies; long delay; } jiq_data; #define SCHEDULER_QUEUE ((task_queue *) 1) - - static void jiq_print_tasklet(unsigned long); static DECLARE_TASKLET(jiq_tasklet, jiq_print_tasklet, (unsigned long)&jiq_data); - /* * Do the printing; return non-zero if the task should be rescheduled. */ @@ -78,7 +75,7 @@ static int jiq_print(void *ptr) { struct clientdata *data = ptr; int len = data->len; - char *buf = data->buf; + struct seq_file *m = data->m; unsigned long j = jiffies; if (len > LIMIT) { @@ -86,19 +83,21 @@ static int jiq_print(void *ptr) return 0; } - if (len == 0) - len = sprintf(buf," time delta preempt pid cpu command\n"); - else - len =0; + if (len == 0) { + seq_printf(m, " time delta preempt pid cpu command\n"); + len = m->count; + } else { + len = 0; + } /* intr_count is only exported since 1.3.5, but 1.99.4 is needed anyways */ - len += sprintf(buf+len, "%9li %4li %3i %5i %3i %s\n", + seq_printf(m, "%9li %4li %3i %5i %3i %s\n", j, j - data->jiffies, preempt_count(), current->pid, smp_processor_id(), current->comm); + len += m->count; data->len += len; - data->buf += len; data->jiffies = j; return 1; } @@ -110,65 +109,81 @@ static int jiq_print(void *ptr) static void jiq_print_wq(struct work_struct *work) { struct clientdata *data = container_of(work, struct clientdata, jiq_work); - + if (! jiq_print (data)) return; - + schedule_work(&jiq_data.jiq_work); } static void jiq_print_wq_delayed(struct work_struct *work) { struct clientdata *data = container_of(work, struct clientdata, jiq_delayed_work.work); - + if (! jiq_print (data)) return; - + schedule_delayed_work(&jiq_data.jiq_delayed_work, data->delay); } -static int jiq_read_wq(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +static int jiq_read_wq_show(struct seq_file *m, void *v) { DEFINE_WAIT(wait); - + jiq_data.len = 0; /* nothing printed, yet */ - jiq_data.buf = buf; /* print in this place */ + jiq_data.m = m; /* print in this place */ jiq_data.jiffies = jiffies; /* initial time */ jiq_data.delay = 0; - + prepare_to_wait(&jiq_wait, &wait, TASK_INTERRUPTIBLE); schedule_work(&jiq_data.jiq_work); schedule(); finish_wait(&jiq_wait, &wait); - *eof = 1; - return jiq_data.len; + return 0; } +static int jiq_read_wq_open(struct inode *inode, struct file *file) +{ + return single_open(file, jiq_read_wq_show, NULL); +} + +static const struct file_operations jiq_read_wq_fops = { + .open = jiq_read_wq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; -static int jiq_read_wq_delayed(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +static int jiq_read_wq_delayed_show(struct seq_file *m, void *v) { DEFINE_WAIT(wait); jiq_data.len = 0; /* nothing printed, yet */ - jiq_data.buf = buf; /* print in this place */ + jiq_data.m = m; /* print in this place */ jiq_data.jiffies = jiffies; /* initial time */ jiq_data.delay = delay; - + prepare_to_wait(&jiq_wait, &wait, TASK_INTERRUPTIBLE); schedule_delayed_work(&jiq_data.jiq_delayed_work, delay); schedule(); finish_wait(&jiq_wait, &wait); - *eof = 1; - return jiq_data.len; + return 0; } +static int jiq_read_wq_delayed_open(struct inode *inode, struct file *file) +{ + return single_open(file, jiq_read_wq_delayed_show, NULL); +} - +static const struct file_operations jiq_read_wq_delayed_fops = { + .open = jiq_read_wq_delayed_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* * Call jiq_print from a tasklet @@ -179,24 +194,29 @@ static void jiq_print_tasklet(unsigned long ptr) tasklet_schedule (&jiq_tasklet); } - - -static int jiq_read_tasklet(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +static int jiq_read_tasklet_show(struct seq_file *m, void *v) { jiq_data.len = 0; /* nothing printed, yet */ - jiq_data.buf = buf; /* print in this place */ + jiq_data.m = m; /* print in this place */ jiq_data.jiffies = jiffies; /* initial time */ tasklet_schedule(&jiq_tasklet); interruptible_sleep_on(&jiq_wait); /* sleep till completion */ - *eof = 1; - return jiq_data.len; + return 0; } +static int jiq_read_tasklet_open(struct inode *inode, struct file *file) +{ + return single_open(file, jiq_read_tasklet_show, NULL); +} - +static const struct file_operations jiq_read_tasklet_fops = { + .open = jiq_read_tasklet_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* * This one, instead, tests out the timers. @@ -210,13 +230,10 @@ static void jiq_timedout(unsigned long ptr) wake_up_interruptible(&jiq_wait); /* awake the process */ } - -static int jiq_read_run_timer(char *buf, char **start, off_t offset, - int len, int *eof, void *data) +static int jiq_read_run_timer_show(struct seq_file *m, void *v) { - jiq_data.len = 0; /* prepare the argument for jiq_print() */ - jiq_data.buf = buf; + jiq_data.m = m; jiq_data.jiffies = jiffies; init_timer(&jiq_timer); /* init the timer structure */ @@ -229,11 +246,20 @@ static int jiq_read_run_timer(char *buf, char **start, off_t offset, interruptible_sleep_on(&jiq_wait); /* RACE */ del_timer_sync(&jiq_timer); /* in case a signal woke us up */ - *eof = 1; - return jiq_data.len; + return 0; } +static int jiq_read_run_timer_open(struct inode *inode, struct file *file) +{ + return single_open(file, jiq_read_run_timer_show, NULL); +} +static const struct file_operations jiq_read_run_timer_fops = { + .open = jiq_read_run_timer_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; /* * the init/clean material @@ -241,15 +267,14 @@ static int jiq_read_run_timer(char *buf, char **start, off_t offset, static int jiq_init(void) { - /* this line is in jiq_init() */ INIT_WORK(&jiq_data.jiq_work, jiq_print_wq); INIT_DELAYED_WORK(&jiq_data.jiq_delayed_work, jiq_print_wq_delayed); - create_proc_read_entry("jiqwq", 0, NULL, jiq_read_wq, NULL); - create_proc_read_entry("jiqwqdelay", 0, NULL, jiq_read_wq_delayed, NULL); - create_proc_read_entry("jitimer", 0, NULL, jiq_read_run_timer, NULL); - create_proc_read_entry("jiqtasklet", 0, NULL, jiq_read_tasklet, NULL); + proc_create("jiqwq", 0, NULL, &jiq_read_wq_fops); + proc_create("jiqwqdelay", 0, NULL, &jiq_read_wq_delayed_fops); + proc_create("jitimer", 0, NULL, &jiq_read_run_timer_fops); + proc_create("jiqtasklet", 0, NULL, &jiq_read_tasklet_fops); return 0; /* succeed */ } |