jiq.c
上传用户:wudi5211
上传日期:2010-01-21
资源大小:607k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

C/C++

  1. /*
  2.  * jiq.c -- the just-in-queue module
  3.  *
  4.  * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
  5.  * Copyright (C) 2001 O'Reilly & Associates
  6.  *
  7.  * The source code in this file can be freely used, adapted,
  8.  * and redistributed in source or binary form, so long as an
  9.  * acknowledgment appears in derived source files.  The citation
  10.  * should list that the code comes from the book "Linux Device
  11.  * Drivers" by Alessandro Rubini and Jonathan Corbet, published
  12.  * by O'Reilly & Associates.   No warranty is attached;
  13.  * we cannot take responsibility for errors or fitness for use.
  14.  *
  15.  * $Id: jiq.c,v 1.15 2001/07/18 22:28:16 rubini Exp $
  16.  */
  17.  
  18. /* BUGS: the module is not reentrant: only one file can be read at a time
  19.  *       the module usage count is not used: you could remove the module
  20.  *           while reading it, thus asking for troubles.
  21.  */
  22. #ifndef __KERNEL__
  23. #  define __KERNEL__
  24. #endif
  25. #ifndef MODULE
  26. #  define MODULE
  27. #endif
  28. #include <linux/config.h>
  29. #include <linux/module.h>
  30. #include <linux/sched.h>
  31. #include <linux/kernel.h>
  32. #include <linux/fs.h>     /* everything... */
  33. #include <linux/proc_fs.h>
  34. #include <linux/errno.h>  /* error codes */
  35. #include <linux/tqueue.h>
  36. #include <linux/interrupt.h> /* intr_count */
  37. #include "sysdep.h"
  38. /*
  39.  * This module is a silly one: it only embeds short code fragments
  40.  * that show how enqueued tasks `feel' theit environment
  41.  */
  42. #define LIMIT (PAGE_SIZE-128) /* don't print any more after this size */
  43. /*
  44.  * Print information about the current environment. This is called from
  45.  * within the task queues. If the limit is reched, awake the reading
  46.  * process.
  47.  */
  48. DECLARE_WAIT_QUEUE_HEAD (jiq_wait);
  49. struct tq_struct jiq_task; /* global: initialized to zero */
  50. /*
  51.  * Keep track of info we need between task queue runs.
  52.  */
  53. struct clientdata {
  54.     int len;
  55.     char *buf;
  56.     unsigned long jiffies;
  57.     task_queue *queue;
  58. } jiq_data;
  59. #define SCHEDULER_QUEUE ((task_queue *) 1)
  60. #ifdef HAVE_TASKLETS
  61. void jiq_print_tasklet (unsigned long);
  62. DECLARE_TASKLET (jiq_tasklet, jiq_print_tasklet, (unsigned long) &jiq_data);
  63. #endif /* HAVE_TASKLETS */
  64. /*
  65.  * Do the printing; return non-zero if the task should be rescheduled.
  66.  */
  67. int jiq_print(void *ptr)
  68. {
  69.   struct clientdata *data = (struct clientdata *)ptr;
  70.   int len = data->len;
  71.   char *buf = data->buf;
  72.   unsigned long j = jiffies;
  73.   if (len > LIMIT) { 
  74.       wake_up_interruptible(&jiq_wait);
  75.       return 0;
  76.   }
  77.   if (len == 0)
  78.       len = sprintf(buf,"    time  delta interrupt  pid cpu commandn");
  79.   else
  80.       len =0;
  81.   /* intr_count is only exported since 1.3.5, but 1.99.4 is needed anyways */
  82.   len += sprintf(buf+len,"%9li %3li        %i   %5i %3i %sn",
  83.                  j, j - data->jiffies,
  84.                  in_interrupt (), current->pid, smp_processor_id (), current->comm);
  85.   data->len += len;
  86.   data->buf += len;
  87.   data->jiffies = j;
  88.   return 1;
  89. }
  90. /*
  91.  * Call jiq_print from a task queue
  92.  */
  93. void jiq_print_tq(void *ptr)
  94. {
  95.     if (jiq_print (ptr)) {
  96.         struct clientdata *data = (struct clientdata *)ptr;
  97.         if (data->queue == SCHEDULER_QUEUE)
  98.     schedule_task(&jiq_task);
  99.         else if (data->queue)
  100.             queue_task(&jiq_task, data->queue);
  101.         if (data->queue == &tq_immediate)
  102.             mark_bh(IMMEDIATE_BH); /* this one needs to be marked */
  103.     }
  104. }
  105. /*
  106.  * Use the scheduler queue  -- /proc/jiqsched
  107.  */
  108. int jiq_read_sched(char *buf, char **start, off_t offset,
  109.                    int len, int *eof, void *data)
  110. {
  111.     jiq_data.len = 0;               /* nothing printed, yet */
  112.     jiq_data.buf = buf;             /* print in this place */
  113.     jiq_data.jiffies = jiffies;     /* initial time */
  114.     /* jiq_print will queue_task() again in jiq_data.queue */
  115.     jiq_data.queue = SCHEDULER_QUEUE;
  116.     schedule_task(&jiq_task);             /* ready to run */
  117.     interruptible_sleep_on(&jiq_wait);    /* sleep till completion */
  118.     *eof = 1;
  119.     return jiq_data.len;
  120. }
  121. #ifdef USE_PROC_REGISTER
  122. static int jiq_old_read_sched(char *buf, char **start, off_t offset, int len,
  123.                 int unused)
  124. {
  125.     int eof;
  126.     return jiq_read_sched(buf, start, offset, len, &eof, NULL);
  127. }
  128. struct proc_dir_entry jiq_proc_sched = {
  129.         0,                 /* low_ino: the inode -- dynamic */
  130.         8, "jiqsched",     /* len of name and name */
  131.         S_IFREG | S_IRUGO, /* mode */
  132.         1, 0, 0,           /* nlinks, owner, group */
  133.         0, NULL,           /* size - unused; operations -- use default */
  134.         &jiq_old_read_sched,   /* function used to read data */
  135.         /* nothing more */
  136.     };
  137. #endif
  138. int jiq_read_timer(char *buf, char **start, off_t offset,
  139.                    int len, int *eof, void *data)
  140. {
  141.     jiq_data.len = 0;            /* nothing printed, yet */
  142.     jiq_data.buf = buf;          /* print in this place */
  143.     jiq_data.jiffies = jiffies;  /* initial time */
  144.     jiq_data.queue = &tq_timer;  /* re-register yourself here */
  145.     queue_task(&jiq_task, &tq_timer);     /* ready to run */
  146.     interruptible_sleep_on(&jiq_wait);    /* sleep till completion */
  147.     *eof = 1;
  148.     return jiq_data.len;
  149. }
  150. #ifdef USE_PROC_REGISTER
  151. static int jiq_old_read_timer(char *buf, char **start, off_t offset, int len,
  152.                 int unused)
  153. {
  154.     int eof;
  155.     return jiq_read_timer(buf, start, offset, len, &eof, NULL);
  156. }
  157. struct proc_dir_entry jiq_proc_timer = {
  158.         0,                 /* low_ino: the inode -- dynamic */
  159.         8, "jiqtimer",     /* len of name and name */
  160.         S_IFREG | S_IRUGO, /* mode */
  161.         1, 0, 0,           /* nlinks, owner, group */
  162.         0, NULL,           /* size - unused; operations -- use default */
  163.         &jiq_old_read_timer,   /* function used to read data */
  164.         /* nothing more */
  165.     };
  166. #endif
  167. int jiq_read_immed(char *buf, char **start, off_t offset,
  168.                    int len, int *eof, void *data)
  169. {
  170.     jiq_data.len = 0;                /* nothing printed, yet */
  171.     jiq_data.buf = buf;              /* print in this place */
  172.     jiq_data.jiffies = jiffies;      /* initial time */
  173.     jiq_data.queue = &tq_immediate;  /* re-register yourself here */
  174.     queue_task(&jiq_task, &tq_immediate); /* ready to run */
  175.     mark_bh(IMMEDIATE_BH);
  176.     interruptible_sleep_on(&jiq_wait);    /* sleep till completion */
  177.     *eof = 1;
  178.     return jiq_data.len;
  179. }
  180. #ifdef USE_PROC_REGISTER
  181. static int jiq_old_read_immed(char *buf, char **start, off_t offset, int len,
  182.                 int unused)
  183. {
  184.     int eof;
  185.     return jiq_read_immed(buf, start, offset, len, &eof, NULL);
  186. }
  187. struct proc_dir_entry jiq_proc_immed = {
  188.         0,                 /* low_ino: the inode -- dynamic */
  189.         8, "jiqimmed",     /* len of name and name */
  190.         S_IFREG | S_IRUGO, /* mode */
  191.         1, 0, 0,           /* nlinks, owner, group */
  192.         0, NULL,           /* size - unused; operations -- use default */
  193.         &jiq_old_read_immed,   /* function used to read data */
  194.         /* nothing more */
  195.     };
  196. #endif
  197. #ifdef HAVE_TASKLETS
  198. /*
  199.  * Call jiq_print from a tasklet
  200.  */
  201. void jiq_print_tasklet(unsigned long ptr)
  202. {
  203.     if (jiq_print ((void *) ptr))
  204.         tasklet_schedule (&jiq_tasklet);
  205. }
  206. int jiq_read_tasklet(char *buf, char **start, off_t offset, int len,
  207.                 int *eof, void *data)
  208. {
  209.     jiq_data.len = 0;                /* nothing printed, yet */
  210.     jiq_data.buf = buf;              /* print in this place */
  211.     jiq_data.jiffies = jiffies;      /* initial time */
  212.     tasklet_schedule(&jiq_tasklet);
  213.     interruptible_sleep_on(&jiq_wait);    /* sleep till completion */
  214.     *eof = 1;
  215.     return jiq_data.len;
  216. }
  217. /* No PROC_REGISTER junk since tasklets postdate all that */
  218. #endif /* HAVE_TASKLETS */
  219. /*
  220.  * This one, instead, tests out the timers.
  221.  */
  222. struct timer_list jiq_timer;
  223. void jiq_timedout(unsigned long ptr)
  224. {
  225.     jiq_print((void *)ptr);            /* print a line */
  226.     wake_up_interruptible(&jiq_wait);  /* awake the process */
  227. }
  228. int jiq_read_run_timer(char *buf, char **start, off_t offset,
  229.                    int len, int *eof, void *data)
  230. {
  231.     jiq_data.len = 0;           /* prepare the argument for jiq_print() */
  232.     jiq_data.buf = buf;
  233.     jiq_data.jiffies = jiffies;
  234.     jiq_data.queue = NULL;      /* don't requeue */
  235.     init_timer(&jiq_timer);              /* init the timer structure */
  236.     jiq_timer.function = jiq_timedout;
  237.     jiq_timer.data = (unsigned long)&jiq_data;
  238.     jiq_timer.expires = jiffies + HZ; /* one second */
  239.     jiq_print(&jiq_data);   /* print and go to sleep */
  240.     add_timer(&jiq_timer);
  241.     interruptible_sleep_on(&jiq_wait);
  242.     del_timer_sync(&jiq_timer);  /* in case a signal woke us up */
  243.     
  244.     *eof = 1;
  245.     return jiq_data.len;
  246. }
  247. #ifdef USE_PROC_REGISTER
  248. static int jiq_old_read_run_timer(char *buf, char **start, off_t offset, int len,
  249.                 int unused)
  250. {
  251.     int eof;
  252.     return jiq_read_run_timer(buf, start, offset, len, &eof, NULL);
  253. }
  254. struct proc_dir_entry jiq_proc_run_timer = {
  255.         0,                 /* low_ino: the inode -- dynamic */
  256.         7, "jitimer",      /* len of name and name */
  257.         S_IFREG | S_IRUGO, /* mode */
  258.         1, 0, 0,           /* nlinks, owner, group */
  259.         0, NULL,           /* size - unused; operations -- use default */
  260.         &jiq_old_read_run_timer, /* function used to read data */
  261.         /* nothing more */
  262.     };
  263. #endif
  264. /*
  265.  * the init/clean material
  266.  */
  267. int jiq_init(void)
  268. {
  269.     /* these lines are in jiq_init() */
  270.     jiq_task.routine = jiq_print_tq;
  271.     jiq_task.data = (void *)&jiq_data;
  272. #ifdef USE_PROC_REGISTER
  273.     proc_register_dynamic(&proc_root, &jiq_proc_sched);
  274.     proc_register_dynamic(&proc_root, &jiq_proc_timer);
  275.     proc_register_dynamic(&proc_root, &jiq_proc_immed);
  276.     proc_register_dynamic(&proc_root, &jiq_proc_run_timer);
  277. #else
  278.     create_proc_read_entry("jiqsched", 0, NULL, jiq_read_sched, NULL);
  279.     create_proc_read_entry("jiqtimer", 0, NULL, jiq_read_timer, NULL);
  280.     create_proc_read_entry("jiqimmed", 0, NULL, jiq_read_immed, NULL);
  281.     create_proc_read_entry("jitimer", 0, NULL, jiq_read_run_timer, NULL);
  282. #ifdef HAVE_TASKLETS
  283.     create_proc_read_entry("jiqtasklet", 0, NULL, jiq_read_tasklet, NULL);
  284. #endif
  285. #endif
  286. #ifndef JIT_DEBUG
  287.     EXPORT_NO_SYMBOLS;
  288. #endif
  289.     return 0; /* succeed */
  290. }
  291. void jiq_cleanup(void)
  292. {
  293. #ifdef USE_PROC_REGISTER
  294.     proc_unregister(&proc_root, jiq_proc_sched.low_ino);
  295.     proc_unregister(&proc_root, jiq_proc_timer.low_ino);
  296.     proc_unregister(&proc_root, jiq_proc_immed.low_ino);
  297.     proc_unregister(&proc_root, jiq_proc_run_timer.low_ino);
  298. #else
  299.     remove_proc_entry("jiqsched", 0);
  300.     remove_proc_entry("jiqtimer", 0);
  301.     remove_proc_entry("jiqimmed", 0);
  302.     remove_proc_entry("jitimer", 0);
  303. #ifdef HAVE_TASKLETS
  304.     remove_proc_entry("jiqtasklet", 0);
  305. #endif
  306. #endif
  307. }
  308. module_init(jiq_init);
  309. module_exit(jiq_cleanup);