krxtimod.c 4.5 KB

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