su_port.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*
  2. * This file is part of the Sofia-SIP package
  3. *
  4. * Copyright (C) 2005 Nokia Corporation.
  5. *
  6. * Contact: Pekka Pessi <pekka.pessi@nokia.com>
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  21. * 02110-1301 USA
  22. *
  23. */
  24. /**@ingroup su_wait
  25. * @CFILE su_port.c
  26. *
  27. * OS-Independent Socket Syncronization Interface.
  28. *
  29. * This looks like nth reincarnation of "reactor". It implements the
  30. * poll/select/WaitForMultipleObjects and message passing functionality.
  31. * This is virtual implementation:
  32. *
  33. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  34. * @author Kai Vehmanen <kai.vehmanen@nokia.com>
  35. *
  36. * @date Created: Tue Sep 14 15:51:04 1999 ppessi
  37. */
  38. #include "config.h"
  39. #define SU_CLONE_T su_msg_t
  40. #define su_port_s su_virtual_port_s
  41. #include "su_port.h"
  42. #include <sofia-sip/su_string.h>
  43. #include <stdlib.h>
  44. /** Create the default su_port_t implementation. */
  45. su_port_t *su_default_port_create(void)
  46. {
  47. #if HAVE_EPOLL
  48. return su_epoll_port_create();
  49. #elif HAVE_KQUEUE
  50. return su_kqueue_port_create();
  51. #elif HAVE_SYS_DEVPOLL_H
  52. return su_devpoll_port_create();
  53. #elif HAVE_POLL_PORT
  54. return su_poll_port_create();
  55. #elif HAVE_WIN32
  56. return su_wsaevent_port_create();
  57. #elif HAVE_SELECT
  58. return su_select_port_create();
  59. #else
  60. return NULL;
  61. #endif
  62. }
  63. int su_default_clone_start(su_root_t *parent,
  64. su_clone_r return_clone,
  65. su_root_magic_t *magic,
  66. su_root_init_f init,
  67. su_root_deinit_f deinit)
  68. {
  69. #if HAVE_EPOLL
  70. return su_epoll_clone_start(parent, return_clone, magic, init, deinit);
  71. #elif HAVE_KQUEUE
  72. return su_kqueue_clone_start(parent, return_clone, magic, init, deinit);
  73. #elif HAVE_SYS_DEVPOLL_H
  74. return su_devpoll_clone_start(parent, return_clone, magic, init, deinit);
  75. #elif HAVE_POLL_PORT
  76. return su_poll_clone_start(parent, return_clone, magic, init, deinit);
  77. #elif HAVE_WIN32
  78. return su_wsaevent_clone_start(parent, return_clone, magic, init, deinit);
  79. #elif HAVE_SELECT
  80. return su_select_clone_start(parent, return_clone, magic, init, deinit);
  81. #else
  82. errno = ENOSYS;
  83. return -1;
  84. #endif
  85. }
  86. static su_port_create_f *preferred_su_port_create;
  87. static su_clone_start_f *preferred_su_clone_start;
  88. /** Explicitly set the preferred su_port_t implementation.
  89. *
  90. * @sa su_epoll_port_create(), su_poll_port_create(), su_select_port_create()
  91. */
  92. void su_port_prefer(su_port_create_f *create,
  93. su_clone_start_f *start)
  94. {
  95. if (create) preferred_su_port_create = create;
  96. if (start) preferred_su_clone_start = start;
  97. }
  98. static
  99. void su_port_set_system_preferences(char const *name)
  100. {
  101. su_port_create_f *create = preferred_su_port_create;
  102. su_clone_start_f *start = preferred_su_clone_start;
  103. if (name == NULL)
  104. ;
  105. #if HAVE_EPOLL
  106. else if (su_casematch(name, "epoll")) {
  107. create = su_epoll_port_create;
  108. start = su_epoll_clone_start;
  109. }
  110. #endif
  111. #if HAVE_KQUEUE
  112. else if (su_casematch(name, "kqueue")) {
  113. create = su_kqueue_port_create;
  114. start = su_kqueue_clone_start;
  115. }
  116. #endif
  117. #if HAVE_SYS_DEVPOLL_H
  118. else if (su_casematch(name, "devpoll")) {
  119. create = su_devpoll_port_create;
  120. start = su_devpoll_clone_start;
  121. }
  122. #endif
  123. #if HAVE_POLL_PORT
  124. else if (su_casematch(name, "poll")) {
  125. create = su_poll_port_create;
  126. start = su_poll_clone_start;
  127. }
  128. #endif
  129. #if HAVE_WIN32
  130. else if (su_casematch(name, "wsaevent")) {
  131. create = su_wsaevent_port_create;
  132. start = su_wsaevent_clone_start;
  133. }
  134. #elif HAVE_SELECT
  135. else if (su_casematch(name, "select")) {
  136. create = su_select_port_create;
  137. start = su_select_clone_start;
  138. }
  139. #endif
  140. if (create == NULL)
  141. create = su_default_port_create;
  142. if (!preferred_su_port_create ||
  143. preferred_su_port_create == su_default_port_create)
  144. preferred_su_port_create = create;
  145. if (start == NULL)
  146. start = su_default_clone_start;
  147. if (!preferred_su_clone_start ||
  148. preferred_su_clone_start == su_default_clone_start)
  149. preferred_su_clone_start = start;
  150. }
  151. /** Create the preferred su_port_t implementation. */
  152. su_port_t *su_port_create(void)
  153. {
  154. if (preferred_su_port_create == NULL)
  155. su_port_set_system_preferences(getenv("SU_PORT"));
  156. return preferred_su_port_create();
  157. }
  158. /** Return name of the su_port_t instance. */
  159. char const *su_port_name(su_port_t const *port)
  160. {
  161. return port->sup_vtable->su_port_name(port);
  162. }
  163. /* ========================================================================
  164. * su_clone_t
  165. */
  166. /**@ingroup su_wait
  167. *
  168. * @page su_clone_t Clone Objects
  169. *
  170. * The process may be divided into many tasks via cloning. Several tasks may
  171. * run in context of one thread, or each task may be run by its own thread.
  172. * However, only a single thread can execute code within a task. There can
  173. * be a 1-to-N mapping from thread to tasks. Thus, software using tasks can
  174. * be executed by multiple threads in a multithreaded environment and by a
  175. * single thread in a singlethreaded environment.
  176. *
  177. * The clones are useful for handling tasks that can be executed by a
  178. * separate threads, but which do not block excessively. When threads are
  179. * not available or they are not needed, clones can also be run in a
  180. * single-threaded mode. Running in single-threaded mode is especially
  181. * useful while debugging.
  182. *
  183. * A clone task is created with function su_clone_start(). Each clone has
  184. * its own root object (su_root_t), which holds a context pointer
  185. * (su_root_magic_t *). The context object can be different from that of
  186. * parent task.
  187. *
  188. * When a clone is started, the clone initialization function is called. The
  189. * initialization function should do whatever initialization there is to be
  190. * performed, register I/O events and timers, and then return. If the
  191. * initialization is successful, the clone task reverts to run the event
  192. * loop and invoking the event callbacks until its parent stops it by
  193. * calling su_clone_wait() which invokes the deinit function. The clone task
  194. * is destroyed when the deinit function returns.
  195. *
  196. * The public API consists of following functions:
  197. * - su_clone_start()
  198. * - su_clone_task()
  199. * - su_clone_wait()
  200. * - su_clone_forget()
  201. *
  202. * @note
  203. * There is only one event loop for each thread which can be shared by
  204. * multiple clone tasks. Therefore, the clone tasks can not explicitly run
  205. * or step the event loop, but they are limited to event callbacks. A clone
  206. * task may not call su_root_break(), su_root_run() or su_root_step().
  207. */
  208. static int su_root_init_nothing(su_root_t *root, su_root_magic_t *magic)
  209. {
  210. return 0;
  211. }
  212. static void su_root_deinit_nothing(su_root_t *root, su_root_magic_t *magic)
  213. {
  214. }
  215. /** Start a clone task.
  216. *
  217. * Allocate and initialize a sub-task. Depending on the su_root_threading()
  218. * settings, a separate thread may be created to execute the sub-task. The
  219. * sub-task is represented by clone handle to the rest of the application.
  220. * The function su_clone_start() returns the clone handle in @a
  221. * return_clone. The clone handle is used to communicate with the newly
  222. * created clone task using messages.
  223. *
  224. * A new #su_root_t object is created for the sub-task with the @a magic as
  225. * the root context pointer. Because the sub-task may or may not have its
  226. * own thread, all its activity must be scheduled via this root object. In
  227. * other words, the sub-task can be schedule
  228. * -# I/O events with su_root_register()
  229. * -# timers with su_timer_set(), su_timer_set_at() or su_timer_run()
  230. * -# messages with su_msg_send().
  231. *
  232. * Messages can also be used to pass information between tasks or threads.
  233. *
  234. * In multi-threaded implementation, su_clone_start() launches a new thread,
  235. * and the initialization routine is executed by this newly created thread.
  236. * The calling thread blocks until the initialization routine completes. If
  237. * the initialization routine returns #su_success (0), the sub-task is
  238. * considered to be created successfully. After the successful
  239. * initialization, the sub-task continues to execeute the function
  240. * su_root_run().
  241. *
  242. * In single-threaded implementations, just a new root object is created.
  243. * The initialization routine is called directly from su_clone_start().
  244. *
  245. * If the initalization function @a init fails, the sub-task (either the
  246. * newly created thread or the current thread executing the su_clone_start()
  247. * function) calls the deinitialization function, and su_clone_start()
  248. * returns NULL.
  249. *
  250. * @param parent root to be cloned
  251. * @param return_clone reference to a clone [OUT]
  252. * @param magic pointer to user data
  253. * @param init initialization function
  254. * @param deinit deinitialization function
  255. *
  256. * @return 0 if successfull, -1 upon an error.
  257. *
  258. * @note Earlier documentation mentioned that @a parent could be NULL. That
  259. * feature has never been implemented, however.
  260. *
  261. * @sa su_root_threading(), su_clone_task(), su_clone_stop(), su_clone_wait(),
  262. * su_clone_forget().
  263. */
  264. int su_clone_start(su_root_t *parent,
  265. su_clone_r return_clone,
  266. su_root_magic_t *magic,
  267. su_root_init_f init,
  268. su_root_deinit_f deinit)
  269. {
  270. su_port_vtable_t const *svp;
  271. if (init == NULL)
  272. init = su_root_init_nothing;
  273. if (deinit == NULL)
  274. deinit = su_root_deinit_nothing;
  275. if (parent == NULL || parent->sur_threading) {
  276. if (preferred_su_clone_start == NULL)
  277. su_port_set_system_preferences(getenv("SU_PORT"));
  278. return preferred_su_clone_start(parent, return_clone, magic, init, deinit);
  279. }
  280. svp = parent->sur_task->sut_port->sup_vtable;
  281. if (svp->su_port_start_shared == NULL)
  282. return su_seterrno(EINVAL);
  283. /* Return a task sharing the same port. */
  284. return svp->su_port_start_shared(parent, return_clone, magic, init, deinit);
  285. }
  286. /** Get reference to a clone task.
  287. *
  288. * @param clone Clone pointer
  289. *
  290. * @return A reference to the task structure of the clone.
  291. */
  292. _su_task_r su_clone_task(su_clone_r clone)
  293. {
  294. return su_msg_to(clone);
  295. }
  296. /**Forget the clone.
  297. *
  298. * Normally, the clone task executes until it is stopped. If the parent
  299. * task does not need to stop the task, it can "forget" the clone. The
  300. * clone exits independently of the parent task.
  301. *
  302. * @param rclone Reference to the clone.
  303. */
  304. void su_clone_forget(su_clone_r rclone)
  305. {
  306. su_msg_destroy(rclone);
  307. }
  308. /** Stop the clone.
  309. *
  310. * This can used only if clone task has sent no report messages (messages
  311. * with delivery report sent back to clone).
  312. *
  313. * @deprecated. Use su_clone_wait().
  314. */
  315. void su_clone_stop(su_clone_r rclone)
  316. {
  317. su_msg_send(rclone);
  318. }
  319. /** Stop a clone and wait until it is has completed.
  320. *
  321. * The function su_clone_wait() is used to stop the clone task and wait
  322. * until it has cleaned up. The clone task is destroyed asynchronously. The
  323. * parent sends a message to clone, clone deinitializes itself and then
  324. * replies. After the reply message is received by the parent, it will send
  325. * a third message back to clone.
  326. *
  327. * The parent destroy all messages to or from clone task before calling
  328. * su_clone_wait(). The parent task may not send any messages to the clone
  329. * after calling su_clone_wait(). The su_clone_wait() function blocks until
  330. * the cloned task is destroyed. During that time, the parent task must be
  331. * prepared to process all the messages sent by clone task. This includes
  332. * all the messages sent by clone before destroy the message reached the
  333. * clone.
  334. */
  335. void su_clone_wait(su_root_t *root, su_clone_r rclone)
  336. {
  337. if (rclone[0]) {
  338. assert(root == NULL || root == su_msg_from(rclone)->sut_root);
  339. su_port_wait(rclone);
  340. }
  341. }
  342. /** Pause a clone.
  343. *
  344. * Obtain an exclusive lock on clone's private data.
  345. *
  346. * @retval 0 if successful (and clone is paused)
  347. * @retval -1 upon an error
  348. *
  349. * @deprecated Never implemented.
  350. */
  351. int su_clone_pause(su_clone_r rclone)
  352. {
  353. #if 0
  354. su_root_t *cloneroot = su_task_root(su_msg_to(rclone));
  355. if (!cloneroot)
  356. return (errno = EFAULT), -1;
  357. if (SU_ROOT_OWN_THREAD(cloneroot))
  358. /* We own it already */
  359. return 0;
  360. return su_port_pause(cloneroot->sur_port);
  361. #else
  362. return errno = ENOSYS, -1;
  363. #endif
  364. }
  365. /** Resume a clone.
  366. *
  367. * Give up an exclusive lock on clone's private data.
  368. *
  369. * @retval 0 if successful (and clone is resumed)
  370. * @retval -1 upon an error
  371. *
  372. * @deprecated Never implemented.
  373. */
  374. int su_clone_resume(su_clone_r rclone)
  375. {
  376. #if 0
  377. su_root_t *cloneroot = su_task_root(su_msg_to(rclone));
  378. if (!cloneroot)
  379. return (errno = EFAULT), -1;
  380. if (SU_ROOT_OWN_THREAD(cloneroot))
  381. /* We cannot give it away */
  382. return 0;
  383. return su_port_resume(cloneroot->sur_port);
  384. #else
  385. return errno = ENOSYS, -1;
  386. #endif
  387. }
  388. /** Wait for clone to exit.
  389. *
  390. * @internal
  391. *
  392. * Called by su_clone_wait().
  393. */
  394. void su_port_wait(su_clone_r rclone)
  395. {
  396. su_port_t *cloneport;
  397. assert(*rclone);
  398. cloneport = su_msg_to(rclone)->sut_port;
  399. cloneport->sup_vtable->su_port_wait(rclone);
  400. }
  401. int su_port_execute(su_task_r const task,
  402. int (*function)(void *), void *arg,
  403. int *return_value)
  404. {
  405. if (!task->sut_port->sup_vtable->su_port_execute)
  406. return errno = ENOSYS, -1;
  407. return task->sut_port->sup_vtable->
  408. su_port_execute(task, function, arg, return_value);
  409. }
  410. #if notyet && nomore
  411. int su_port_pause(su_port_t *self)
  412. {
  413. assert(self->sup_vtable->su_port_pause);
  414. return self->sup_vtable->su_port_pause(self);
  415. }
  416. int su_port_resume(su_port_t *self)
  417. {
  418. assert(self->sup_vtable->su_port_resume);
  419. return self->sup_vtable->su_port_resume(self);
  420. }
  421. #endif