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

嵌入式Linux

开发平台:

C/C++

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