local_timer.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2007 iptelorg GmbH
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. /* local, per process timer routines
  28. * WARNING: this should be used only within the same process, the timers
  29. * are not multi-process safe or multi-thread safe
  30. * (there are no locks)
  31. *
  32. * History:
  33. * --------
  34. * 2006-02-03 created by andrei
  35. */
  36. /*!
  37. * \file
  38. * \brief SIP-router core ::
  39. * \ingroup core
  40. * Module: \ref core
  41. */
  42. #include "timer.h"
  43. #include "timer_funcs.h"
  44. #include "dprint.h"
  45. #include "tcp_conn.h"
  46. #include "mem/mem.h"
  47. #include "compiler_opt.h"
  48. #include "local_timer.h"
  49. /* init a local_timer handle
  50. * returns 0 on success, -1 on error */
  51. int init_local_timer(struct local_timer *t, ticks_t crt_ticks)
  52. {
  53. int r;
  54. /* initial values */
  55. memset(t, 0, sizeof(*t));
  56. t->prev_ticks=crt_ticks;
  57. /* init timer structures */
  58. for (r=0; r<H0_ENTRIES; r++)
  59. _timer_init_list(&t->timer_lst.h0[r]);
  60. for (r=0; r<H1_ENTRIES; r++)
  61. _timer_init_list(&t->timer_lst.h1[r]);
  62. for (r=0; r<H2_ENTRIES; r++)
  63. _timer_init_list(&t->timer_lst.h2[r]);
  64. _timer_init_list(&t->timer_lst.expired);
  65. DBG("init_local_timer: timer_list between %p and %p\n",
  66. &t->timer_lst.h0[0], &t->timer_lst.h2[H2_ENTRIES]);
  67. return 0;
  68. }
  69. void destroy_local_timer(struct local_timer* lt)
  70. {
  71. }
  72. /* generic add timer entry to the timer lists function (see _timer_add)
  73. * tl->expire must be set previously, delta is the difference in ticks
  74. * from current time to the timer desired expire (should be tl->expire-*tick)
  75. * If you don't know delta, you probably want to call _timer_add instead.
  76. */
  77. static inline int _local_timer_dist_tl(struct local_timer* h,
  78. struct timer_ln* tl, ticks_t delta)
  79. {
  80. if (likely(delta<H0_ENTRIES)){
  81. if (unlikely(delta==0)){
  82. LM_WARN("0 expire timer added\n");
  83. _timer_add_list(&h->timer_lst.expired, tl);
  84. }else{
  85. _timer_add_list( &h->timer_lst.h0[tl->expire & H0_MASK], tl);
  86. }
  87. }else if (likely(delta<(H0_ENTRIES*H1_ENTRIES))){
  88. _timer_add_list(&h->timer_lst.h1[(tl->expire & H1_H0_MASK)>>H0_BITS],
  89. tl);
  90. }else{
  91. _timer_add_list(&h->timer_lst.h2[tl->expire>>(H1_BITS+H0_BITS)], tl);
  92. }
  93. return 0;
  94. }
  95. static inline void local_timer_redist(struct local_timer* l,
  96. ticks_t t, struct timer_head *h)
  97. {
  98. struct timer_ln* tl;
  99. struct timer_ln* tmp;
  100. timer_foreach_safe(tl, tmp, h){
  101. _local_timer_dist_tl(l, tl, tl->expire-t);
  102. }
  103. /* clear the current list */
  104. _timer_init_list(h);
  105. }
  106. /* local timer add function (no lock, not multithread or multiprocess safe,
  107. * designed for local process use only)
  108. * t = current ticks
  109. * tl must be filled (the intial_timeout and flags must be set)
  110. * returns -1 on error, 0 on success */
  111. static inline int _local_timer_add(struct local_timer *h, ticks_t t,
  112. struct timer_ln* tl)
  113. {
  114. ticks_t delta;
  115. delta=tl->initial_timeout;
  116. tl->expire=t+delta;
  117. return _local_timer_dist_tl(h, tl, delta);
  118. }
  119. /* "public", safe timer add functions (local process use only)
  120. * adds a timer at delta ticks from the current time
  121. * returns -1 on error, 0 on success
  122. * WARNING: to re-add a deleted or expired timer you must call
  123. * timer_reinit(tl) prior to timer_add
  124. * The default behaviour allows timer_add to add a timer only if it
  125. * has never been added before.*/
  126. int local_timer_add(struct local_timer* h, struct timer_ln* tl, ticks_t delta,
  127. ticks_t crt_ticks)
  128. {
  129. int ret;
  130. if (unlikely(tl->flags & F_TIMER_ACTIVE)){
  131. DBG("timer_add called on an active timer %p (%p, %p),"
  132. " flags %x\n", tl, tl->next, tl->prev, tl->flags);
  133. ret=-1; /* refusing to add active or non-reinit. timer */
  134. goto error;
  135. }
  136. tl->initial_timeout=delta;
  137. if (unlikely((tl->next!=0) || (tl->prev!=0))){
  138. LM_CRIT("called with linked timer: %p (%p, %p)\n", tl, tl->next, tl->prev);
  139. ret=-1;
  140. goto error;
  141. }
  142. tl->flags|=F_TIMER_ACTIVE;
  143. ret=_local_timer_add(h, crt_ticks, tl);
  144. error:
  145. return ret;
  146. }
  147. /* safe timer delete
  148. * deletes tl and inits the list pointer to 0
  149. * WARNING: to be able to reuse a deleted timer you must call
  150. * timer_reinit(tl) on it
  151. *
  152. */
  153. void local_timer_del(struct local_timer* h, struct timer_ln* tl)
  154. {
  155. /* quick exit if timer inactive */
  156. if (unlikely(!(tl->flags & F_TIMER_ACTIVE))){
  157. DBG("timer_del called on an inactive timer %p (%p, %p),"
  158. " flags %x\n", tl, tl->next, tl->prev, tl->flags);
  159. return;
  160. }
  161. if (likely((tl->next!=0)&&(tl->prev!=0))){
  162. _timer_rm_list(tl); /* detach */
  163. tl->next=tl->prev=0;
  164. }else{
  165. DBG("timer_del: (f) timer %p (%p, %p) flags %x "
  166. "already detached\n",
  167. tl, tl->next, tl->prev, tl->flags);
  168. }
  169. }
  170. /* called from timer_handle*/
  171. inline static void local_timer_list_expire(struct local_timer* l,
  172. ticks_t t, struct timer_head* h)
  173. {
  174. struct timer_ln * tl;
  175. ticks_t ret;
  176. /*DBG("timer_list_expire @ ticks = %lu, list =%p\n",
  177. (unsigned long) *ticks, h);
  178. */
  179. while(h->next!=(struct timer_ln*)h){
  180. tl=h->next;
  181. _timer_rm_list(tl); /* detach */
  182. tl->next=tl->prev=0; /* debugging */
  183. /*FIXME: process tcpconn */
  184. ret=tl->f(t, tl, tl->data);
  185. if (ret!=0){
  186. /* not one-shot, re-add it */
  187. if (ret!=(ticks_t)-1) /* ! periodic */
  188. tl->initial_timeout=ret;
  189. _local_timer_add(l, t, tl);
  190. }
  191. }
  192. }
  193. /* run all the handler that expire at t ticks */
  194. static inline void local_timer_expire(struct local_timer* h, ticks_t t)
  195. {
  196. /* trust the compiler for optimizing */
  197. if (unlikely((t & H0_MASK)==0)){ /*r1*/
  198. if (unlikely((t & H1_H0_MASK)==0)){ /*r2*/
  199. local_timer_redist(h, t, &h->timer_lst.h2[t>>(H0_BITS+H1_BITS)]);
  200. }
  201. local_timer_redist(h, t, &h->timer_lst.h1[(t & H1_H0_MASK)>>H0_BITS]);
  202. /*r2 >> H0*/
  203. }
  204. /* run handler immediately, no need to move it to the expired list
  205. * (since no locks are used) */
  206. local_timer_list_expire(h, t, &h->timer_lst.h0[t & H0_MASK]);
  207. }
  208. /* "main" local timer routine, should be called with a proper ticks value
  209. * WARNING: it should never be called twice for the same ticks value
  210. * (it could cause too fast expires for long timers), ticks must be also
  211. * always increasing */
  212. void local_timer_run(struct local_timer* lt, ticks_t saved_ticks)
  213. {
  214. /* protect against time running backwards */
  215. if (unlikely(lt->prev_ticks>=saved_ticks)){
  216. LM_CRIT("backwards or still time\n");
  217. /* try to continue */
  218. lt->prev_ticks=saved_ticks-1;
  219. return;
  220. }
  221. /* go through all the "missed" ticks, taking a possible overflow
  222. * into account */
  223. for (lt->prev_ticks=lt->prev_ticks+1; lt->prev_ticks!=saved_ticks;
  224. lt->prev_ticks++)
  225. local_timer_expire(lt, lt->prev_ticks);
  226. local_timer_expire(lt, lt->prev_ticks); /* do it for saved_ticks too */
  227. local_timer_list_expire(lt, saved_ticks, &lt->timer_lst.expired);
  228. /* WARNING: add_timer(...,0) must go directly to expired list, since
  229. * otherwise there is a race between timer running and adding it
  230. * (it could expire it H0_ENTRIES ticks later instead of 'now')*/
  231. }