timer_proc.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2009 iptelorg GmbH
  5. *
  6. * Permission to use, copy, modify, and distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. /*
  19. * timer_proc.c - separate process timers
  20. * (unrelated to the main fast and slow timers)
  21. */
  22. /*
  23. * History:
  24. * --------
  25. * 2009-03-10 initial version (andrei)
  26. */
  27. /**
  28. * @file
  29. * @brief SIP-router core :: timer - separate process timers
  30. *
  31. * (unrelated to the main fast and slow timers)
  32. *
  33. * @ingroup core
  34. * Module: @ref core
  35. */
  36. #include "timer_proc.h"
  37. #include "cfg/cfg_struct.h"
  38. #include "pt.h"
  39. #include "ut.h"
  40. #include "mem/shm_mem.h"
  41. #include <unistd.h>
  42. /**
  43. * \brief update internal counters for running new basic sec. timers
  44. * @param timers number of basic timer processes
  45. * @return 0 on success; -1 on error
  46. */
  47. int register_basic_timers(int timers)
  48. {
  49. if(register_procs(timers)<0)
  50. return -1;
  51. cfg_register_child(timers);
  52. return 0;
  53. }
  54. /**
  55. * \brief Forks a separate simple sleep() periodic timer
  56. *
  57. * Forks a very basic periodic timer process, that just sleep()s for
  58. * the specified interval and then calls the timer function.
  59. * The new "basic timer" process execution start immediately, the sleep()
  60. * is called first (so the first call to the timer function will happen
  61. * \<interval\> seconds after the call to fork_basic_timer)
  62. * @param child_id @see fork_process()
  63. * @param desc @see fork_process()
  64. * @param make_sock @see fork_process()
  65. * @param f timer function/callback
  66. * @param param parameter passed to the timer function
  67. * @param interval interval in seconds.
  68. * @return pid of the new process on success, -1 on error
  69. * (doesn't return anything in the child process)
  70. */
  71. int fork_basic_timer(int child_id, char* desc, int make_sock,
  72. timer_function* f, void* param, int interval)
  73. {
  74. int pid;
  75. pid=fork_process(child_id, desc, make_sock);
  76. if (pid<0) return -1;
  77. if (pid==0){
  78. /* child */
  79. if (cfg_child_init()) return -1;
  80. for(;;){
  81. sleep(interval);
  82. cfg_update();
  83. f(get_ticks(), param); /* ticks in s for compatibility with old
  84. timers */
  85. }
  86. }
  87. /* parent */
  88. return pid;
  89. }
  90. /**
  91. * \brief Forks a separate simple microsecond-sleep() periodic timer
  92. *
  93. * Forks a very basic periodic timer process, that just us-sleep()s for
  94. * the specified interval and then calls the timer function.
  95. * The new "basic timer" process execution start immediately, the us-sleep()
  96. * is called first (so the first call to the timer function will happen
  97. * \<interval\> microseconds after the call to fork_basic_utimer)
  98. * @param child_id @see fork_process()
  99. * @param desc @see fork_process()
  100. * @param make_sock @see fork_process()
  101. * @param f timer function/callback
  102. * @param param parameter passed to the timer function
  103. * @param uinterval interval in micro-seconds.
  104. * @return pid of the new process on success, -1 on error
  105. * (doesn't return anything in the child process)
  106. */
  107. int fork_basic_utimer(int child_id, char* desc, int make_sock,
  108. utimer_function* f, void* param, int uinterval)
  109. {
  110. int pid;
  111. ticks_t ts;
  112. pid=fork_process(child_id, desc, make_sock);
  113. if (pid<0) return -1;
  114. if (pid==0){
  115. /* child */
  116. if (cfg_child_init()) return -1;
  117. for(;;){
  118. sleep_us(uinterval);
  119. cfg_update();
  120. ts = get_ticks_raw();
  121. f(TICKS_TO_MS(ts), param); /* ticks in mili-seconds */
  122. }
  123. }
  124. /* parent */
  125. return pid;
  126. }
  127. /**
  128. * \brief Forks a timer process based on the local timer
  129. *
  130. * Forks a separate timer process running a local_timer.h type of timer
  131. * A pointer to the local_timer handle (allocated in shared memory) is
  132. * returned in lt_h. It can be used to add/delete more timers at runtime
  133. * (via local_timer_add()/local_timer_del() a.s.o).
  134. * If timers are added from separate processes, some form of locking must be
  135. * used (all the calls to local_timer* must be enclosed by locks if it
  136. * cannot be guaranteed that they cannot execute in the same time)
  137. * The timer "engine" must be run manually from the child process. For
  138. * example a very simple local timer process that just runs a single
  139. * periodic timer can be started in the following way:
  140. * struct local_timer* lt_h;
  141. *
  142. * pid=fork_local_timer_process(...., &lt_h);
  143. * if (pid==0){
  144. * timer_init(&my_timer, my_timer_f, 0, 0);
  145. * local_timer_add(&lt_h, &my_timer, S_TO_TICKS(10), get_ticks_raw());
  146. * while(1) { sleep(1); local_timer_run(lt, get_ticks_raw()); }
  147. * }
  148. *
  149. * @param child_id @see fork_process()
  150. * @param desc @see fork_process()
  151. * @param make_sock @see fork_process()
  152. * @param lt_h local_timer handler
  153. * @return pid to the parent, 0 to the child, -1 if error.
  154. */
  155. int fork_local_timer_process(int child_id, char* desc, int make_sock,
  156. struct local_timer** lt_h)
  157. {
  158. int pid;
  159. struct local_timer* lt;
  160. lt=shm_malloc(sizeof(*lt));
  161. if (lt==0) goto error;
  162. if (init_local_timer(lt, get_ticks_raw())<0) goto error;
  163. pid=fork_process(child_id, desc, make_sock);
  164. if (pid<0) goto error;
  165. *lt_h=lt;
  166. return pid;
  167. error:
  168. if (lt) shm_free(lt);
  169. return -1;
  170. }
  171. /**
  172. * \brief update internal counters for running new sync sec. timers
  173. * @param timers number of basic timer processes
  174. * @return 0 on success; -1 on error
  175. */
  176. int register_sync_timers(int timers)
  177. {
  178. if(register_procs(timers)<0)
  179. return -1;
  180. cfg_register_child(timers);
  181. return 0;
  182. }
  183. /**
  184. * \brief Forks a separate simple sleep() -&- sync periodic timer
  185. *
  186. * Forks a very basic periodic timer process, that just sleep()s for
  187. * the specified interval and then calls the timer function.
  188. * The new "sync timer" process execution start immediately, the sleep()
  189. * is called first (so the first call to the timer function will happen
  190. * \<interval\> seconds after the call to fork_sync_timer)
  191. * @param child_id @see fork_process()
  192. * @param desc @see fork_process()
  193. * @param make_sock @see fork_process()
  194. * @param f timer function/callback
  195. * @param param parameter passed to the timer function
  196. * @param interval interval in seconds.
  197. * @return pid of the new process on success, -1 on error
  198. * (doesn't return anything in the child process)
  199. */
  200. int fork_sync_timer(int child_id, char* desc, int make_sock,
  201. timer_function* f, void* param, int interval)
  202. {
  203. int pid;
  204. ticks_t ts1 = 0;
  205. ticks_t ts2 = 0;
  206. pid=fork_process(child_id, desc, make_sock);
  207. if (pid<0) return -1;
  208. if (pid==0){
  209. /* child */
  210. interval *= 1000; /* miliseconds */
  211. ts2 = interval;
  212. if (cfg_child_init()) return -1;
  213. for(;;){
  214. if (ts2>interval)
  215. sleep_us(1000); /* 1 milisecond sleep to catch up */
  216. else
  217. sleep_us(ts2*1000); /* microseconds sleep */
  218. ts1 = get_ticks_raw();
  219. cfg_update();
  220. f(TICKS_TO_S(ts1), param); /* ticks in sec for compatibility with old
  221. timers */
  222. /* adjust the next sleep duration */
  223. ts2 = interval - TICKS_TO_MS(get_ticks_raw()) + TICKS_TO_MS(ts1);
  224. }
  225. }
  226. /* parent */
  227. return pid;
  228. }
  229. /**
  230. * \brief Forks a separate simple microsecond-sleep() -&- sync periodic timer
  231. *
  232. * Forks a very basic periodic timer process, that just us-sleep()s for
  233. * the specified interval and then calls the timer function.
  234. * The new "sync timer" process execution start immediately, the us-sleep()
  235. * is called first (so the first call to the timer function will happen
  236. * \<interval\> microseconds after the call to fork_basic_utimer)
  237. * @param child_id @see fork_process()
  238. * @param desc @see fork_process()
  239. * @param make_sock @see fork_process()
  240. * @param f timer function/callback
  241. * @param param parameter passed to the timer function
  242. * @param uinterval interval in micro-seconds.
  243. * @return pid of the new process on success, -1 on error
  244. * (doesn't return anything in the child process)
  245. */
  246. int fork_sync_utimer(int child_id, char* desc, int make_sock,
  247. utimer_function* f, void* param, int uinterval)
  248. {
  249. int pid;
  250. ticks_t ts1 = 0;
  251. ticks_t ts2 = 0;
  252. pid=fork_process(child_id, desc, make_sock);
  253. if (pid<0) return -1;
  254. if (pid==0){
  255. /* child */
  256. ts2 = uinterval;
  257. if (cfg_child_init()) return -1;
  258. for(;;){
  259. if(ts2>uinterval)
  260. sleep_us(1);
  261. else
  262. sleep_us(ts2);
  263. ts1 = get_ticks_raw();
  264. cfg_update();
  265. f(TICKS_TO_MS(ts1), param); /* ticks in mili-seconds */
  266. ts2 = uinterval - get_ticks_raw() + ts1;
  267. }
  268. }
  269. /* parent */
  270. return pid;
  271. }
  272. /* vi: set ts=4 sw=4 tw=79:ai:cindent: */