context.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/kernel/context.c
  3.  *
  4.  * Mechanism for running arbitrary tasks in process context
  5.  *
  6.  * dwmw2@redhat.com: Genesis
  7.  *
  8.  * andrewm@uow.edu.au: 2.4.0-test12
  9.  * - Child reaping
  10.  * - Support for tasks which re-add themselves
  11.  * - flush_scheduled_tasks.
  12.  */
  13. #define __KERNEL_SYSCALLS__
  14. #include <linux/module.h>
  15. #include <linux/kernel.h>
  16. #include <linux/sched.h>
  17. #include <linux/init.h>
  18. #include <linux/unistd.h>
  19. #include <linux/signal.h>
  20. #include <linux/completion.h>
  21. static DECLARE_TASK_QUEUE(tq_context);
  22. static DECLARE_WAIT_QUEUE_HEAD(context_task_wq);
  23. static DECLARE_WAIT_QUEUE_HEAD(context_task_done);
  24. static int keventd_running;
  25. static struct task_struct *keventd_task;
  26. static int need_keventd(const char *who)
  27. {
  28. if (keventd_running == 0)
  29. printk(KERN_ERR "%s(): keventd has not startedn", who);
  30. return keventd_running;
  31. }
  32. int current_is_keventd(void)
  33. {
  34. int ret = 0;
  35. if (need_keventd(__FUNCTION__))
  36. ret = (current == keventd_task);
  37. return ret;
  38. }
  39. /**
  40.  * schedule_task - schedule a function for subsequent execution in process context.
  41.  * @task: pointer to a &tq_struct which defines the function to be scheduled.
  42.  *
  43.  * May be called from interrupt context.  The scheduled function is run at some
  44.  * time in the near future by the keventd kernel thread.  If it can sleep, it
  45.  * should be designed to do so for the minimum possible time, as it will be
  46.  * stalling all other scheduled tasks.
  47.  *
  48.  * schedule_task() returns non-zero if the task was successfully scheduled.
  49.  * If @task is already residing on a task queue then schedule_task() fails
  50.  * to schedule your task and returns zero.
  51.  */
  52. int schedule_task(struct tq_struct *task)
  53. {
  54. int ret;
  55. need_keventd(__FUNCTION__);
  56. ret = queue_task(task, &tq_context);
  57. wake_up(&context_task_wq);
  58. return ret;
  59. }
  60. static int context_thread(void *startup)
  61. {
  62. struct task_struct *curtask = current;
  63. DECLARE_WAITQUEUE(wait, curtask);
  64. struct k_sigaction sa;
  65. daemonize();
  66. strcpy(curtask->comm, "keventd");
  67. keventd_running = 1;
  68. keventd_task = curtask;
  69. spin_lock_irq(&curtask->sigmask_lock);
  70. siginitsetinv(&curtask->blocked, sigmask(SIGCHLD));
  71. recalc_sigpending(curtask);
  72. spin_unlock_irq(&curtask->sigmask_lock);
  73. complete((struct completion *)startup);
  74. /* Install a handler so SIGCLD is delivered */
  75. sa.sa.sa_handler = SIG_IGN;
  76. sa.sa.sa_flags = 0;
  77. siginitset(&sa.sa.sa_mask, sigmask(SIGCHLD));
  78. do_sigaction(SIGCHLD, &sa, (struct k_sigaction *)0);
  79. /*
  80.  * If one of the functions on a task queue re-adds itself
  81.  * to the task queue we call schedule() in state TASK_RUNNING
  82.  */
  83. for (;;) {
  84. set_task_state(curtask, TASK_INTERRUPTIBLE);
  85. add_wait_queue(&context_task_wq, &wait);
  86. if (TQ_ACTIVE(tq_context))
  87. set_task_state(curtask, TASK_RUNNING);
  88. schedule();
  89. remove_wait_queue(&context_task_wq, &wait);
  90. run_task_queue(&tq_context);
  91. wake_up(&context_task_done);
  92. if (signal_pending(curtask)) {
  93. while (waitpid(-1, (unsigned int *)0, __WALL|WNOHANG) > 0)
  94. ;
  95. spin_lock_irq(&curtask->sigmask_lock);
  96. flush_signals(curtask);
  97. recalc_sigpending(curtask);
  98. spin_unlock_irq(&curtask->sigmask_lock);
  99. }
  100. }
  101. }
  102. /**
  103.  * flush_scheduled_tasks - ensure that any scheduled tasks have run to completion.
  104.  *
  105.  * Forces execution of the schedule_task() queue and blocks until its completion.
  106.  *
  107.  * If a kernel subsystem uses schedule_task() and wishes to flush any pending
  108.  * tasks, it should use this function.  This is typically used in driver shutdown
  109.  * handlers.
  110.  *
  111.  * The caller should hold no spinlocks and should hold no semaphores which could
  112.  * cause the scheduled tasks to block.
  113.  */
  114. static struct tq_struct dummy_task;
  115. void flush_scheduled_tasks(void)
  116. {
  117. int count;
  118. DECLARE_WAITQUEUE(wait, current);
  119. /*
  120.  * Do it twice. It's possible, albeit highly unlikely, that
  121.  * the caller queued a task immediately before calling us,
  122.  * and that the eventd thread was already past the run_task_queue()
  123.  * but not yet into wake_up(), so it woke us up before completing
  124.  * the caller's queued task or our new dummy task.
  125.  */
  126. add_wait_queue(&context_task_done, &wait);
  127. for (count = 0; count < 2; count++) {
  128. set_current_state(TASK_UNINTERRUPTIBLE);
  129. /* Queue a dummy task to make sure we get kicked */
  130. schedule_task(&dummy_task);
  131. /* Wait for it to complete */
  132. schedule();
  133. }
  134. remove_wait_queue(&context_task_done, &wait);
  135. }
  136. int start_context_thread(void)
  137. {
  138. static struct completion startup __initdata = COMPLETION_INITIALIZER(startup);
  139. kernel_thread(context_thread, &startup, CLONE_FS | CLONE_FILES);
  140. wait_for_completion(&startup);
  141. return 0;
  142. }
  143. EXPORT_SYMBOL(schedule_task);
  144. EXPORT_SYMBOL(flush_scheduled_tasks);