本文共 6461 字,大约阅读时间需要 21 分钟。
共享隊列 - /*
- * jiq.c -- the just-in-queue module
- *
- * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
- * Copyright (C) 2001 O'Reilly & Associates
- *
- * The source code in this file can be freely used, adapted,
- * and redistributed in source or binary form, so long as an
- * acknowledgment appears in derived source files. The citation
- * should list that the code comes from the book "Linux Device
- * Drivers" by Alessandro Rubini and Jonathan Corbet, published
- * by O'Reilly & Associates. No warranty is attached;
- * we cannot take responsibility for errors or fitness for use.
- *
- * $Id: jiq.c,v 1.7 2004/09/26 07:02:43 gregkh Exp $
- */
-
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/init.h>
-
- #include <linux/sched.h>
- #include <linux/kernel.h>
- #include <linux/fs.h> /* everything... */
- #include <linux/proc_fs.h>
- #include <linux/errno.h> /* error codes */
- #include <linux/workqueue.h>
- #include <linux/preempt.h>
- #include <linux/interrupt.h> /* tasklets */
-
-
-
- /*
- * The delay for the delayed workqueue timer file.
- */
- 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
- */
-
- #define LIMIT (512) /* don't print any more after this size */
-
- /*
- * Print information about the current environment. This is called from
- * within the task queues. If the limit is reched, awake the reading
- * process.
- */
- static DECLARE_WAIT_QUEUE_HEAD (jiq_wait);
-
-
- static struct work_struct jiq_work;
- static struct delayed_work jiq_work_delay;
-
-
- /*
- * Keep track of info we need between task queue runs.
- */
- static struct clientdata {
- int len;
- char *buf;
- unsigned long jiffies;
- unsigned 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.
- */
- static int jiq_print(void *ptr)
- {
- struct clientdata *data = ptr;
- int len = data->len;
- char *buf = data->buf;
- unsigned long j = jiffies;
-
- //error , full
- if (len > LIMIT)
- {
- wake_up_interruptible(&jiq_wait);
- return 0;
- }
-
- //the first time to show the message
- if (len == 0)
- len = sprintf(buf," time delta preempt pid cpu commandn");
- else
- len =0; //init again
-
- /* intr_count is only exported since 1.3.5, but 1.99.4 is needed anyways */
- len += sprintf(buf, "%9li %4li %3i %5i %3i %sn",
- j, j - data->jiffies,
- preempt_count(), current->pid, smp_processor_id(),
- current->comm);
-
- data->len += len;
- data->buf += len;
- data->jiffies = j;
- return 1;
- }
-
-
- /*
- * Call jiq_print from a work queue
- */
- static void jiq_print_wq(struct work_struct *ptr) /* warning: assignment from incompatible pointer type*/
- {
- struct clientdata *data = &jiq_data;
-
- if (! jiq_print (data))
- return;
-
- //to schedule again, so jiq_work <===> jiq_print_wq() will be call again
- if (data->delay)
- schedule_delayed_work( &jiq_work_delay, data->delay);
- else
- schedule_work(&jiq_work);
- }
-
-
-
- static int jiq_read_wq(char *buf, char **start, off_t offset,
- int len, int *eof, void *data)
- {
- DEFINE_WAIT(wait);
-
- jiq_data.len = 0; /* nothing printed, yet */
- jiq_data.buf = buf; /* print in this place */
- jiq_data.jiffies = jiffies; /* initial time */
- jiq_data.delay = 0;
-
- //add jiq_wait into the waitquene
- prepare_to_wait(&jiq_wait, &wait, TASK_INTERRUPTIBLE);
- //use this method, jiq_work <===> jiq_print_wq() will be call(here is very important)
- schedule_work(&jiq_work);
- //here sleep and wait
- schedule();
- //cleanup the waitquene
- finish_wait(&jiq_wait, &wait);
-
- *eof = 1;
- return jiq_data.len;
- }
-
-
- static int jiq_read_wq_delayed(char *buf, char **start, off_t offset,
- int len, int *eof, void *data)
- {
- DEFINE_WAIT(wait);
-
- jiq_data.len = 0; /* nothing printed, yet */
- jiq_data.buf = buf; /* 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_work_delay, delay);
- schedule();
- finish_wait(&jiq_wait, &wait);
-
- *eof = 1;
- return jiq_data.len;
- }
-
-
-
-
- /*
- * Call jiq_print from a tasklet
- */
- static void jiq_print_tasklet(unsigned long ptr)
- {
- if (!jiq_print ((void *) ptr))
- return;
-
- //to schedule it again
- tasklet_schedule (&jiq_tasklet);
- }
-
-
-
- static int jiq_read_tasklet(char *buf, char **start, off_t offset, int len,
- int *eof, void *data)
- {
- jiq_data.len = 0; /* nothing printed, yet */
- jiq_data.buf = buf; /* print in this place */
- jiq_data.jiffies = jiffies; /* initial time */
-
- tasklet_schedule(&jiq_tasklet);
- //here interruptible_sleep_on is not a good method
- //try to use 手動休眠
- interruptible_sleep_on(&jiq_wait); /* sleep utill completion */
-
- *eof = 1;
- return jiq_data.len;
- }
-
-
-
-
- /*
- * This one, instead, tests out the timers.
- */
-
- static struct timer_list jiq_timer;
-
- static void jiq_timedout(unsigned long ptr)
- {
- struct clientdata *data = ptr;
- //jiq_print((void *)ptr); /* print a line */
- //wake_up_interruptible(&jiq_wait); /* awake the process */
-
- if (! jiq_print (data))
- {
- wake_up_interruptible(&jiq_wait); /* awake the process */
- return;
- }
- //update the timer
- mod_timer(&jiq_timer, jiq_timer.expires+HZ);
- }
-
-
- static int jiq_read_run_timer(char *buf, char **start, off_t offset,
- int len, int *eof, void *data)
- {
-
- jiq_data.len = 0; /* prepare the argument for jiq_print() */
- jiq_data.buf = buf;
- jiq_data.jiffies = jiffies;
-
- init_timer(&jiq_timer); /* init the timer structure */
- jiq_timer.function = jiq_timedout;
- jiq_timer.data = (unsigned long)&jiq_data;
- jiq_timer.expires = jiffies + HZ; /* one second */
-
- jiq_print(&jiq_data); /* print and go to sleep */
- add_timer(&jiq_timer);
- interruptible_sleep_on(&jiq_wait); /* RACE */
- del_timer_sync(&jiq_timer); /* in case a signal woke us up */
-
- *eof = 1;
- return jiq_data.len;
- }
-
-
-
- /*
- * the init/clean material
- */
-
- static int jiq_init(void)
- {
-
- /* this line is in jiq_init() */
- INIT_WORK(&jiq_work, jiq_print_wq);
- INIT_DELAYED_WORK(&jiq_work_delay, jiq_print_wq);
- 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("jiqtimer", 0, NULL, jiq_read_run_timer, NULL);
- create_proc_read_entry("jiqtasklet", 0, NULL, jiq_read_tasklet, NULL);
-
- return 0; /* succeed */
- }
-
- static void jiq_cleanup(void)
- {
- remove_proc_entry("jiqwq", NULL);
- remove_proc_entry("jiqwqdelay", NULL);
- remove_proc_entry("jiqtimer", NULL);
- remove_proc_entry("jiqtasklet", NULL);
- }
-
-
- module_init(jiq_init);
- module_exit(jiq_cleanup);
-
- MODULE_LICENSE("Dual BSD/GPL");
转载地址:http://atomi.baihongyu.com/