krxtimod.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* krxtimod.c: RXRPC timeout daemon
  2. *
  3. * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
  4. * Written by David Howells (dhowells@redhat.com)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version
  9. * 2 of the License, or (at your option) any later version.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/init.h>
  13. #include <linux/sched.h>
  14. #include <linux/completion.h>
  15. #include <linux/freezer.h>
  16. #include <rxrpc/rxrpc.h>
  17. #include <rxrpc/krxtimod.h>
  18. #include <asm/errno.h>
  19. #include "internal.h"
  20. static DECLARE_COMPLETION(krxtimod_alive);
  21. static DECLARE_COMPLETION(krxtimod_dead);
  22. static DECLARE_WAIT_QUEUE_HEAD(krxtimod_sleepq);
  23. static int krxtimod_die;
  24. static LIST_HEAD(krxtimod_list);
  25. static DEFINE_SPINLOCK(krxtimod_lock);
  26. static int krxtimod(void *arg);
  27. /*****************************************************************************/
  28. /*
  29. * start the timeout daemon
  30. */
  31. int rxrpc_krxtimod_start(void)
  32. {
  33. int ret;
  34. ret = kernel_thread(krxtimod, NULL, 0);
  35. if (ret < 0)
  36. return ret;
  37. wait_for_completion(&krxtimod_alive);
  38. return ret;
  39. } /* end rxrpc_krxtimod_start() */
  40. /*****************************************************************************/
  41. /*
  42. * stop the timeout daemon
  43. */
  44. void rxrpc_krxtimod_kill(void)
  45. {
  46. /* get rid of my daemon */
  47. krxtimod_die = 1;
  48. wake_up(&krxtimod_sleepq);
  49. wait_for_completion(&krxtimod_dead);
  50. } /* end rxrpc_krxtimod_kill() */
  51. /*****************************************************************************/
  52. /*
  53. * timeout processing daemon
  54. */
  55. static int krxtimod(void *arg)
  56. {
  57. DECLARE_WAITQUEUE(myself, current);
  58. rxrpc_timer_t *timer;
  59. printk("Started krxtimod %d\n", current->pid);
  60. daemonize("krxtimod");
  61. complete(&krxtimod_alive);
  62. /* loop around looking for things to attend to */
  63. loop:
  64. set_current_state(TASK_INTERRUPTIBLE);
  65. add_wait_queue(&krxtimod_sleepq, &myself);
  66. for (;;) {
  67. unsigned long jif;
  68. long timeout;
  69. /* deal with the server being asked to die */
  70. if (krxtimod_die) {
  71. remove_wait_queue(&krxtimod_sleepq, &myself);
  72. _leave("");
  73. complete_and_exit(&krxtimod_dead, 0);
  74. }
  75. try_to_freeze();
  76. /* discard pending signals */
  77. rxrpc_discard_my_signals();
  78. /* work out the time to elapse before the next event */
  79. spin_lock(&krxtimod_lock);
  80. if (list_empty(&krxtimod_list)) {
  81. timeout = MAX_SCHEDULE_TIMEOUT;
  82. }
  83. else {
  84. timer = list_entry(krxtimod_list.next,
  85. rxrpc_timer_t, link);
  86. timeout = timer->timo_jif;
  87. jif = jiffies;
  88. if (time_before_eq((unsigned long) timeout, jif))
  89. goto immediate;
  90. else {
  91. timeout = (long) timeout - (long) jiffies;
  92. }
  93. }
  94. spin_unlock(&krxtimod_lock);
  95. schedule_timeout(timeout);
  96. set_current_state(TASK_INTERRUPTIBLE);
  97. }
  98. /* the thing on the front of the queue needs processing
  99. * - we come here with the lock held and timer pointing to the expired
  100. * entry
  101. */
  102. immediate:
  103. remove_wait_queue(&krxtimod_sleepq, &myself);
  104. set_current_state(TASK_RUNNING);
  105. _debug("@@@ Begin Timeout of %p", timer);
  106. /* dequeue the timer */
  107. list_del_init(&timer->link);
  108. spin_unlock(&krxtimod_lock);
  109. /* call the timeout function */
  110. timer->ops->timed_out(timer);
  111. _debug("@@@ End Timeout");
  112. goto loop;
  113. } /* end krxtimod() */
  114. /*****************************************************************************/
  115. /*
  116. * (re-)queue a timer
  117. */
  118. void rxrpc_krxtimod_add_timer(rxrpc_timer_t *timer, unsigned long timeout)
  119. {
  120. struct list_head *_p;
  121. rxrpc_timer_t *ptimer;
  122. _enter("%p,%lu", timer, timeout);
  123. spin_lock(&krxtimod_lock);
  124. list_del(&timer->link);
  125. /* the timer was deferred or reset - put it back in the queue at the
  126. * right place */
  127. timer->timo_jif = jiffies + timeout;
  128. list_for_each(_p, &krxtimod_list) {
  129. ptimer = list_entry(_p, rxrpc_timer_t, link);
  130. if (time_before(timer->timo_jif, ptimer->timo_jif))
  131. break;
  132. }
  133. list_add_tail(&timer->link, _p); /* insert before stopping point */
  134. spin_unlock(&krxtimod_lock);
  135. wake_up(&krxtimod_sleepq);
  136. _leave("");
  137. } /* end rxrpc_krxtimod_add_timer() */
  138. /*****************************************************************************/
  139. /*
  140. * dequeue a timer
  141. * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued
  142. */
  143. int rxrpc_krxtimod_del_timer(rxrpc_timer_t *timer)
  144. {
  145. int ret = 0;
  146. _enter("%p", timer);
  147. spin_lock(&krxtimod_lock);
  148. if (list_empty(&timer->link))
  149. ret = -ENOENT;
  150. else
  151. list_del_init(&timer->link);
  152. spin_unlock(&krxtimod_lock);
  153. wake_up(&krxtimod_sleepq);
  154. _leave(" = %d", ret);
  155. return ret;
  156. } /* end rxrpc_krxtimod_del_timer() */