su_root.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334
  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_root.c
  26. * OS-independent synchronization interface.
  27. * @internal
  28. *
  29. * @author Pekka Pessi <Pekka.Pessi@nokia.com>
  30. *
  31. * @date Created: Tue Sep 14 15:51:04 1999 ppessi
  32. */
  33. #include "config.h"
  34. #include <stdlib.h>
  35. #include <assert.h>
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <errno.h>
  39. #include "sofia-sip/su.h"
  40. #if SU_HAVE_PTHREADS
  41. #include <pthread.h>
  42. #endif
  43. struct su_root_s;
  44. #define SU_ROOT_MAGIC_T struct su_root_magic_s
  45. #define SU_WAKEUP_ARG_T struct su_wakeup_arg_s
  46. #define SU_TIMER_ARG_T struct su_timer_arg_s
  47. #include "su_port.h"
  48. #include "sofia-sip/su_alloc.h"
  49. /**@ingroup su_wait
  50. *
  51. * @page su_root_t Tasks and root objects
  52. *
  53. * A task is the basic execution unit for the Sofia event-driven programming
  54. * model. According to the model, the program can ask that the event loop
  55. * invokes a callback function when a certain event occurs. Such events
  56. * include @ref su_root_register "I/O activity", @ref su_timer_t "timers" or
  57. * a @ref su_msg_t "message" from other task. The event loop is run with
  58. * function su_root_run() or su_root_step().
  59. *
  60. * Root object gives access to the task control. The root object represents
  61. * the task to the code running within task. Through the root, the task code
  62. * can access its context object (magic) and thread-synchronization features
  63. * like wait objects, timers, and messages.
  64. *
  65. * When a message is sent between tasks, a task reference #su_task_r is used
  66. * to reprent the task address. Reference counting is used to make sure that
  67. * the task references stay valid.
  68. *
  69. * The public API contains following functions:
  70. * - su_root_create() [Do not call from cloned task]
  71. * - su_root_destroy() [Do not call from cloned task]
  72. * - su_root_magic()
  73. * - su_root_register()
  74. * - su_root_deregister()
  75. * - su_root_unregister()
  76. * - su_root_threading()
  77. * - su_root_run() [Do not call from cloned task]
  78. * - su_root_break() [Do not call from cloned task]
  79. * - su_root_step() [Do not call from cloned task]
  80. * - su_root_get_max_defer()
  81. * - su_root_set_max_defer()
  82. * - su_root_task()
  83. *
  84. * New tasks can be created via su_clone_start() function.
  85. */
  86. /**@ingroup su_wait
  87. *
  88. * @page su_root_register Registering Wait Objects
  89. *
  90. * When application expects I/O events, it can create a wait object and
  91. * register it, a callback function and a context pointer to the #su_root_t
  92. * object using the su_root_register() function. Whenever the wait object
  93. * receives an event, the registered @link ::su_wakeup_f callback function
  94. * @endlink is invoked.
  95. *
  96. * When successful, the su_root_register() returns an small non-negative
  97. * integer representing the registration. The registration can be
  98. * manipulated with su_root_eventmask() function, for instance, when sending
  99. * through a socket block, the application can add SU_WAIT_OUT event to the
  100. * mask.
  101. *
  102. * The registration can be removed using su_root_deregister() function.
  103. */
  104. /**@ingroup su_wait
  105. *
  106. * Contains hint of number of sockets supported by su_root_t */
  107. int su_root_size_hint = 64;
  108. /* ====================================================================== */
  109. _su_task_r su_task_new(su_task_r task, su_root_t *root, su_port_t *port);
  110. int su_task_attach(su_task_r self, su_root_t *root);
  111. int su_task_detach(su_task_r self);
  112. int su_timer_reset_all(su_timer_t **t0, su_task_r);
  113. /* =========================================================================
  114. * Tasks
  115. */
  116. /** NULL task. */
  117. su_task_r const su_task_null = SU_TASK_R_INIT;
  118. #define SU_TASK_ZAP(t, f) \
  119. while (t->sut_port) { \
  120. su_port_decref(t->sut_port, #f); t->sut_port = NULL; break; }
  121. #define SU_TASK_ZAPP(t, f) \
  122. do { if (t->sut_port) { \
  123. su_port_decref(t->sut_port, #f); t->sut_port = NULL; } \
  124. t->sut_root = NULL; } while(0)
  125. /**
  126. * Initialize a task handle with su_task_null.
  127. *
  128. * @param task task handle
  129. *
  130. * @return A reference to the initialized task handle.
  131. */
  132. _su_task_r su_task_init(su_task_r task)
  133. {
  134. assert(task);
  135. memset(task, 0, sizeof(su_task_r));
  136. return task;
  137. }
  138. /**
  139. * Destroy a task handle
  140. *
  141. * @param task task handle
  142. */
  143. void su_task_deinit(su_task_r task)
  144. {
  145. assert(task);
  146. SU_TASK_ZAP(task, su_task_deinit);
  147. task->sut_root = NULL;
  148. }
  149. /**
  150. * Create a new task handle.
  151. *
  152. * @param task task reference
  153. * @param root pointer to root object
  154. * @param port pointer to port object
  155. *
  156. * @return New task handle.
  157. */
  158. _su_task_r su_task_new(su_task_r task, su_root_t *root, su_port_t *port)
  159. {
  160. assert(task);
  161. task->sut_root = root;
  162. if ((task->sut_port = port)) {
  163. su_port_incref(port, "su_task_new");
  164. }
  165. return task;
  166. }
  167. /**
  168. * Duplicates a task handle.
  169. *
  170. * @param dst destination task reference
  171. * @param src source task reference
  172. */
  173. void su_task_copy(su_task_r dst, su_task_r const src)
  174. {
  175. su_port_t *port;
  176. assert(src); assert(dst);
  177. SU_TASK_ZAP(dst, su_task_copy);
  178. port = src->sut_port;
  179. if (port) {
  180. su_port_incref(port, "su_task_copy");
  181. }
  182. dst[0] = src[0];
  183. }
  184. #define SU_TASK_COPY(d, s, by) (void)((d)[0]=(s)[0], \
  185. (s)->sut_port?(void)su_port_incref(s->sut_port, #by):(void)0)
  186. /**
  187. * Moves a task handle.
  188. *
  189. * @param dst destination task reference
  190. * @param src source task reference
  191. */
  192. void su_task_move(su_task_r dst, su_task_r src)
  193. {
  194. SU_TASK_ZAP(dst, su_task_move);
  195. dst[0] = src[0];
  196. src->sut_port = 0;
  197. src->sut_root = 0;
  198. }
  199. /**
  200. * Compare two tasks with each other.
  201. *
  202. * @param a First task
  203. * @param b Second task
  204. *
  205. * @retval negative number, if a < b
  206. * @retval positive number, if a > b
  207. * @retval 0, if a == b.
  208. */
  209. int su_task_cmp(su_task_r const a, su_task_r const b)
  210. {
  211. intptr_t retval = (char *)a->sut_port - (char *)b->sut_port;
  212. if (retval == 0)
  213. retval = (char *)a->sut_root - (char *)b->sut_root;
  214. if (sizeof(retval) != sizeof(int)) {
  215. if (retval < 0)
  216. retval = -1;
  217. else if (retval > 0)
  218. retval = 1;
  219. }
  220. return (int)retval;
  221. }
  222. /**
  223. * Tests if a task is running.
  224. *
  225. * @param task task handle
  226. *
  227. * @retval true (nonzero) if task is not stopped,
  228. * @retval zero if it is null or stopped.
  229. *
  230. * @note A task sharing thread with another task is considered stopped when
  231. * ever the the main task is stopped.
  232. */
  233. int su_task_is_running(su_task_r const task)
  234. {
  235. return task && task->sut_root && su_port_is_running(task->sut_port);
  236. }
  237. /** @internal
  238. * Attach a root object to the task handle.
  239. *
  240. * @param self task handle
  241. * @param root pointer to the root object
  242. *
  243. * @retval 0 if successful,
  244. * @retval -1 otherwise.
  245. */
  246. int su_task_attach(su_task_r self, su_root_t *root)
  247. {
  248. if (self->sut_port) {
  249. self->sut_root = root;
  250. return 0;
  251. }
  252. else
  253. return -1;
  254. }
  255. /**
  256. * Get root pointer attached to a task handle.
  257. *
  258. * @param self task handle
  259. *
  260. * @return
  261. * A pointer to root object attached to the task handle, or NULL if no root
  262. * object has been attached.
  263. */
  264. su_root_t *su_task_root(su_task_r const self)
  265. {
  266. if (self->sut_port) return self->sut_root; else return NULL;
  267. }
  268. #if 0
  269. /** @internal
  270. * Detach a root pointer from task handle.
  271. * @bug Not used anymore.
  272. */
  273. int su_task_detach(su_task_r self)
  274. {
  275. self->sut_root = NULL;
  276. return 0;
  277. }
  278. #endif
  279. /**
  280. * Return the timer list associated with given task.
  281. *
  282. * @param task task handle
  283. *
  284. * @return A timer list of the task.
  285. */
  286. su_timer_queue_t *su_task_timers(su_task_r const task)
  287. {
  288. return task->sut_port ? su_port_timers(task->sut_port) : NULL;
  289. }
  290. /**Return the queue for deferrable timers associated with given task.
  291. *
  292. * @param task task handle
  293. *
  294. * @return A timer list of the task.
  295. *
  296. * @NEW_1_12_11
  297. */
  298. su_timer_queue_t *su_task_deferrable(su_task_r const task)
  299. {
  300. return task ? su_port_deferrable(task->sut_port) : NULL;
  301. }
  302. /** Wakeup a task.
  303. *
  304. * Wake up a task. This function is mainly useful when using deferrable
  305. * timers executed upon wakeup.
  306. *
  307. * @param task task handle
  308. *
  309. * @retval 0 if succesful
  310. * @retval -1 upon an error
  311. *
  312. * @NEW_1_12_11
  313. */
  314. int su_task_wakeup(su_task_r const task)
  315. {
  316. return task ? su_port_wakeup(task->sut_port) : -1;
  317. }
  318. /** Execute the @a function by @a task thread.
  319. *
  320. * @retval 0 if successful
  321. * @retval -1 upon an error
  322. */
  323. int su_task_execute(su_task_r const task,
  324. int (*function)(void *), void *arg,
  325. int *return_value)
  326. {
  327. int dummy;
  328. if (function == NULL)
  329. return (errno = EFAULT), -1;
  330. if (return_value == NULL)
  331. return_value = &dummy;
  332. if (!su_port_own_thread(task->sut_port)) {
  333. return su_port_execute(task, function, arg, return_value);
  334. }
  335. else {
  336. int value = function(arg);
  337. if (return_value)
  338. *return_value = value;
  339. return 0;
  340. }
  341. }
  342. /* Note that is *not* necessary same as su_root_t,
  343. * as su_root_t can be extended */
  344. #define sur_port sur_task->sut_port
  345. #define sur_root sur_task->sut_root
  346. #define SU_ROOT_OWN_THREAD(r) (r->sur_port && su_port_own_thread(r->sur_port))
  347. /** Create a reactor object.
  348. *
  349. * Allocate and initialize the instance of su_root_t.
  350. *
  351. * @param magic pointer to user data
  352. *
  353. * @return A pointer to allocated su_root_t instance, NULL on error.
  354. */
  355. su_root_t *su_root_create(su_root_magic_t *magic)
  356. {
  357. return su_root_create_with_port(magic, su_port_create());
  358. }
  359. /* Initializer used by su_root_clone() */
  360. static int
  361. su_root_clone_initializer(su_root_t *root,
  362. su_root_magic_t *magic)
  363. {
  364. *(su_root_t **)magic = root;
  365. return 0;
  366. }
  367. /** Create a a new root object sharing port/thread with existing one.
  368. *
  369. * Allocate and initialize the instance of su_root_t.
  370. *
  371. * @param magic pointer to user data
  372. *
  373. * @return A pointer to allocated su_root_t instance, NULL on error.
  374. *
  375. * @NEW_1_12_11
  376. */
  377. su_root_t *
  378. su_root_clone(su_root_t *self, su_root_magic_t *magic)
  379. {
  380. int threading = 0, error;
  381. su_clone_r clone;
  382. su_root_t *cloned = NULL;
  383. if (self == NULL)
  384. return NULL;
  385. threading = self->sur_threading, self->sur_threading = 0;
  386. error = su_clone_start(self, clone,
  387. (void *)&cloned, su_root_clone_initializer, NULL);
  388. self->sur_threading = threading;
  389. if (error)
  390. return NULL;
  391. su_clone_forget(clone); /* destroyed with su_root_destroy() */
  392. su_root_set_magic(cloned, magic);
  393. return cloned;
  394. }
  395. /**@internal
  396. *
  397. * Create a reactor object using given message port.
  398. *
  399. * Allocate and initialize the instance of su_root_t. Note that this
  400. * function always uses a reference to su_port_t, even when creating the
  401. * root fails.
  402. *
  403. * @param magic pointer to user data
  404. * @param port pointer to a message port
  405. *
  406. * @return A pointer to allocated su_root_t instance, NULL on error.
  407. */
  408. su_root_t *su_root_create_with_port(su_root_magic_t *magic,
  409. su_port_t *port)
  410. {
  411. su_root_t *self;
  412. if (!port)
  413. return NULL;
  414. self = su_salloc(su_port_home(port), sizeof(struct su_root_s));
  415. if (self) {
  416. self->sur_magic = magic;
  417. #if SU_HAVE_PTHREADS
  418. self->sur_threading = SU_HAVE_PTHREADS;
  419. #else
  420. self->sur_threading = 0;
  421. #endif
  422. /* This one creates a new reference to port */
  423. su_task_new(self->sur_task, self, port);
  424. /* ... so we zap the old one below */
  425. }
  426. su_port_decref(port, "su_root_create_with_port");
  427. return self;
  428. }
  429. /** Destroy a root object.
  430. *
  431. * Stop and free an instance of su_root_t
  432. *
  433. * @param self pointer to a root object.
  434. */
  435. void su_root_destroy(su_root_t *self)
  436. {
  437. su_port_t *port;
  438. int unregistered, reset;
  439. if (!self)
  440. return;
  441. assert(SU_ROOT_OWN_THREAD(self));
  442. self->sur_deiniting = 1;
  443. if (self->sur_deinit) {
  444. su_root_deinit_f deinit = self->sur_deinit;
  445. su_root_magic_t *magic = self->sur_magic;
  446. self->sur_deinit = NULL;
  447. deinit(self, magic);
  448. }
  449. port = self->sur_port; assert(port);
  450. unregistered = su_port_unregister_all(port, self);
  451. reset = su_timer_reset_all(su_task_timers(self->sur_task), self->sur_task);
  452. if (su_task_deferrable(self->sur_task))
  453. reset += su_timer_reset_all(su_task_deferrable(self->sur_task),
  454. self->sur_task);
  455. if (unregistered || reset)
  456. SU_DEBUG_1(("su_root_destroy: "
  457. "%u registered waits, %u timers\n",
  458. unregistered, reset));
  459. SU_TASK_ZAP(self->sur_parent, su_root_destroy);
  460. su_free(su_port_home(port), self);
  461. su_port_decref(port, "su_root_destroy");
  462. }
  463. /** Get instance name.
  464. *
  465. * @param self pointer to a root object
  466. *
  467. * @return Instance name (e.g., "epoll", "devpoll", "select").
  468. *
  469. * @NEW_1_12_6.
  470. */
  471. char const *su_root_name(su_root_t *self)
  472. {
  473. if (!self)
  474. return (void)(errno = EFAULT), NULL;
  475. assert(self->sur_port);
  476. return su_port_name(self->sur_task->sut_port);
  477. }
  478. /** Set the context pointer.
  479. *
  480. * Set the context pointer (magic) of a root object.
  481. *
  482. * @param self pointer to a root object
  483. * @param magic pointer to user data
  484. *
  485. * @retval 0 when successful,
  486. * @retval -1 upon error.
  487. */
  488. int su_root_set_magic(su_root_t *self, su_root_magic_t *magic)
  489. {
  490. if (self == NULL)
  491. return (void)(errno = EFAULT), -1;
  492. assert(SU_ROOT_OWN_THREAD(self));
  493. self->sur_magic = magic;
  494. return 0;
  495. }
  496. /** Set threading option.
  497. *
  498. * Controls whether su_clone_start() creates a new thread.
  499. *
  500. * @param self pointer to a root object
  501. * @param enable if true, enable threading, if false, disable threading
  502. *
  503. * @return True if threading is enabled.
  504. */
  505. int su_root_threading(su_root_t *self, int enable)
  506. {
  507. if (self == NULL)
  508. return (void)(errno = EFAULT), -1;
  509. assert(SU_ROOT_OWN_THREAD(self));
  510. #if SU_HAVE_PTHREADS
  511. self->sur_threading = enable = enable != 0;
  512. return enable;
  513. #else
  514. return 0;
  515. #endif
  516. }
  517. /** Get context pointer.
  518. *
  519. * The function su_root_magic() returns the user context pointer that was
  520. * given input to su_root_create() or su_root_set_magic().
  521. *
  522. * @param self pointer to a root object
  523. *
  524. * @return A pointer to user data
  525. */
  526. su_root_magic_t *su_root_magic(su_root_t *self)
  527. {
  528. if (!self)
  529. return (void)(errno = EFAULT), NULL;
  530. return self->sur_magic;
  531. }
  532. /** Get a GSource */
  533. struct _GSource *su_root_gsource(su_root_t *self)
  534. {
  535. if (!self)
  536. return (void)(errno = EFAULT), NULL;
  537. assert(self->sur_port);
  538. return su_port_gsource(self->sur_port);
  539. }
  540. /** Register a su_wait_t object.
  541. *
  542. * The function su_root_register() registers a su_wait_t object. The wait
  543. * object, a callback function and a argument are stored to the root
  544. * object. The callback function is called, when the wait object is
  545. * signaled.
  546. *
  547. * Please note if identical wait objects are inserted, only first one is
  548. * ever signalled.
  549. *
  550. * @param self pointer to root object
  551. * @param wait pointer to wait object
  552. * @param callback callback function pointer
  553. * @param arg argument given to callback function when it is invoked
  554. * @param priority relative priority of the wait object
  555. * (0 is normal, 1 important, 2 realtime)
  556. *
  557. * @return Nonzero index of the wait object, or -1 upon an error.
  558. */
  559. int su_root_register(su_root_t *self,
  560. su_wait_t *wait,
  561. su_wakeup_f callback,
  562. su_wakeup_arg_t *arg,
  563. int priority)
  564. {
  565. if (!self || !wait)
  566. return (void)(errno = EFAULT), -1;
  567. assert(self->sur_port);
  568. return su_port_register(self->sur_port, self, wait, callback, arg, priority);
  569. }
  570. /** Unregister a su_wait_t object.
  571. *
  572. * The function su_root_unregister() unregisters a su_wait_t object. The
  573. * wait object, a callback function and a argument are removed from the
  574. * root object.
  575. *
  576. * @param self pointer to root object
  577. * @param wait pointer to wait object
  578. * @param callback callback function pointer (may be NULL)
  579. * @param arg argument given to callback function when it is invoked
  580. * (may be NULL)
  581. *
  582. * @return Nonzero index of the wait object, or -1 upon an error.
  583. */
  584. int su_root_unregister(su_root_t *self,
  585. su_wait_t *wait,
  586. su_wakeup_f callback, /* XXX - ignored */
  587. su_wakeup_arg_t *arg)
  588. {
  589. if (!self || !wait)
  590. return (void)(errno = EFAULT), -1;
  591. assert(self->sur_port);
  592. return su_port_unregister(self->sur_port, self, wait, callback, arg);
  593. }
  594. /** Set maximum defer time.
  595. *
  596. * The deferrable timers can be deferred until the task is otherwise
  597. * activated, however, they are deferred no longer than the maximum defer
  598. * time. The maximum defer time determines also the maximum time during
  599. * which task waits for events while running. The maximum defer time is 15
  600. * seconds by default.
  601. *
  602. * Cloned tasks inherit the maximum defer time.
  603. *
  604. * @param self pointer to root object
  605. * @param max_defer maximum defer time in milliseconds
  606. *
  607. * @retval 0 when successful
  608. * @retval -1 upon an error
  609. *
  610. * @sa su_timer_deferrable()
  611. *
  612. * @NEW_1_12_11
  613. */
  614. int su_root_set_max_defer(su_root_t *self, su_duration_t max_defer)
  615. {
  616. if (!self)
  617. return -1;
  618. return su_port_max_defer(self->sur_port, &max_defer, &max_defer);
  619. }
  620. /** Get maximum defer time.
  621. *
  622. * The deferrable timers can be deferred until the task is otherwise
  623. * activated, however, they are deferred no longer than the maximum defer
  624. * time. The maximum defer time is 15 seconds by default.
  625. *
  626. * @param root pointer to root object
  627. *
  628. * @return Maximum defer time
  629. *
  630. * @NEW_1_12_7
  631. */
  632. su_duration_t su_root_get_max_defer(su_root_t const *self)
  633. {
  634. su_duration_t max_defer = SU_WAIT_MAX;
  635. if (self != NULL)
  636. su_port_max_defer(self->sur_port, &max_defer, NULL);
  637. return max_defer;
  638. }
  639. /** Remove a su_wait_t registration.
  640. *
  641. * The function su_root_deregister() deregisters a su_wait_t object. The
  642. * wait object, a callback function and a argument are removed from the
  643. * root object. The wait object is destroyed.
  644. *
  645. * @param self pointer to root object
  646. * @param index registration index
  647. *
  648. * @return Index of the wait object, or -1 upon an error.
  649. */
  650. int su_root_deregister(su_root_t *self, int index)
  651. {
  652. if (!self)
  653. return (void)(errno = EFAULT), -1;
  654. if (index == 0 || index == -1)
  655. return (void)(errno = EINVAL), -1;
  656. assert(self->sur_port);
  657. return su_port_deregister(self->sur_port, index);
  658. }
  659. /** Set mask for a registered event.
  660. *
  661. * The function su_root_eventmask() sets the mask describing events that can
  662. * signal the registered callback.
  663. *
  664. * @param self pointer to root object
  665. * @param index registration index
  666. * @param socket socket
  667. * @param events new event mask
  668. *
  669. * @retval 0 when successful,
  670. * @retval -1 upon an error.
  671. */
  672. int su_root_eventmask(su_root_t *self, int index, int socket, int events)
  673. {
  674. if (!self)
  675. return (void)(errno = EFAULT), -1;
  676. if (index == 0 || index == -1)
  677. return (void)(errno = EINVAL), -1;
  678. assert(self->sur_port);
  679. return su_port_eventmask(self->sur_port, index, socket, events);
  680. }
  681. /** Set multishot mode.
  682. *
  683. * The function su_root_multishot() enables, disables or queries the
  684. * multishot mode for the root. The multishot mode determines how the events
  685. * are scheduled by root. If multishot mode is enabled, root serves all the
  686. * sockets that have received network events. If it is disables, only first
  687. * socket event is served.
  688. *
  689. * @param self pointer to root object
  690. * @param multishot multishot mode (0 => disables, 1 => enables, -1 => query)
  691. *
  692. * @retval 0 multishot mode is disabled
  693. * @retval 1 multishot mode is enabled
  694. * @retval -1 an error occurred
  695. */
  696. int su_root_multishot(su_root_t *self, int multishot)
  697. {
  698. if (!self)
  699. return (void)(errno = EFAULT), -1;
  700. assert(self->sur_port);
  701. return su_port_multishot(self->sur_port, multishot);
  702. }
  703. /** Run event and message loop.
  704. *
  705. * The function su_root_run() runs the root main loop. The root loop waits
  706. * for wait objects and the timers associated with the root object. When any
  707. * wait object is signaled or timer is expired, it invokes the callbacks,
  708. * and returns waiting.
  709. *
  710. * This function returns when su_root_break() is called from a callback.
  711. *
  712. * @param self pointer to root object
  713. *
  714. */
  715. void su_root_run(su_root_t *self)
  716. {
  717. if (!self)
  718. return /* (void)(errno = EFAULT), -1 */;
  719. assert(self->sur_port);
  720. /* return */ su_port_run(self->sur_port);
  721. }
  722. /** Terminate event loop.
  723. *
  724. * The function su_root_break() is used to terminate execution of
  725. * su_root_run(). It can be called from a callback function.
  726. *
  727. * @param self pointer to root object
  728. */
  729. void su_root_break(su_root_t *self)
  730. {
  731. if (!self)
  732. return /* (void)(errno = EFAULT), -1 */;
  733. assert(self->sur_port);
  734. /* return */ su_port_break(self->sur_port);
  735. }
  736. /** Process events, timers and messages.
  737. *
  738. * The function su_root_step() waits for wait objects and the timers
  739. * associated with the root object. When any wait object is signaled or
  740. * timer is expired, it invokes the callbacks.
  741. *
  742. * This function returns when a callback has been invoked or tout
  743. * milliseconds is elapsed.
  744. *
  745. * @param self pointer to root object
  746. * @param tout timeout in milliseconds
  747. *
  748. * @return Milliseconds to the next invocation of timer
  749. * @retval SU_WAIT_FOREVER if there are no active timers or if there was an error
  750. */
  751. su_duration_t su_root_step(su_root_t *self, su_duration_t tout)
  752. {
  753. if (self == NULL)
  754. return (void)(errno = EFAULT), SU_WAIT_FOREVER;
  755. assert(self->sur_port);
  756. return su_port_step(self->sur_port, tout);
  757. }
  758. /**Run event and message loop for given duration.
  759. *
  760. * The function su_root_sleep() runs event loop for @a duration milliseconds.
  761. * The event loop waits for wait objects and the timers associated with the
  762. * @a root object. When any wait object is signaled, timer is expired, or
  763. * message is received, it invokes the callbacks and returns waiting.
  764. *
  765. * @param self pointer to root object
  766. * @param duration milliseconds to run event loop
  767. *
  768. * @retval milliseconds until next timer expiration
  769. */
  770. su_duration_t su_root_sleep(su_root_t *self, su_duration_t duration)
  771. {
  772. su_duration_t retval, accrued = 0;
  773. su_time_t started;
  774. if (self == NULL)
  775. return (void)(errno = EFAULT), SU_WAIT_FOREVER;
  776. assert(self->sur_port);
  777. started = su_now();
  778. do {
  779. retval = su_port_step(self->sur_port, duration - accrued);
  780. accrued = su_duration(su_now(), started);
  781. } while (accrued < duration);
  782. return retval;
  783. }
  784. /** Check wait events in callbacks that take lots of time
  785. *
  786. * This function does a 0 timeout poll() and runs wait objects
  787. *
  788. * @param self pointer to root object
  789. */
  790. int su_root_yield(su_root_t *self)
  791. {
  792. if (self == NULL)
  793. return (void)(errno = EFAULT), SU_WAIT_FOREVER;
  794. assert(self->sur_port);
  795. return su_port_wait_events(self->sur_port, 0);
  796. }
  797. /** Get task reference.
  798. *
  799. * Retrieve the task reference related with the root object.
  800. *
  801. * @param self a pointer to a root object
  802. *
  803. * @return A reference to the task object.
  804. */
  805. _su_task_r su_root_task(su_root_t const *self)
  806. {
  807. if (self)
  808. return self->sur_task;
  809. else
  810. return su_task_null;
  811. }
  812. /** Get parent task reference.
  813. *
  814. * Retrieve the task reference of the parent task associated with the root
  815. * object.
  816. *
  817. * @param self a pointer to a root object
  818. *
  819. * @return A reference to the parent task object.
  820. */
  821. _su_task_r su_root_parent(su_root_t const *self)
  822. {
  823. if (self)
  824. return self->sur_parent;
  825. else
  826. return su_task_null;
  827. }
  828. /** Add a pre-poll callback. */
  829. int su_root_add_prepoll(su_root_t *root,
  830. su_prepoll_f *callback,
  831. su_prepoll_magic_t *magic)
  832. {
  833. if (root == NULL)
  834. return (void)(errno = EFAULT), -1;
  835. assert(root->sur_port);
  836. return su_port_add_prepoll(root->sur_port, root, callback, magic);
  837. }
  838. /** Remove a pre-poll callback */
  839. int su_root_remove_prepoll(su_root_t *root)
  840. {
  841. if (root == NULL)
  842. return (void)(errno = EFAULT), -1;
  843. assert(root->sur_port);
  844. return su_port_remove_prepoll(root->sur_port, root);
  845. }
  846. /** Release the root port for other threads.
  847. *
  848. * @NEW_1_12_7
  849. */
  850. int su_root_release(su_root_t *root)
  851. {
  852. if (root == NULL || root->sur_port == NULL)
  853. return (void)(errno = EFAULT), -1;
  854. return su_port_release(root->sur_port);
  855. }
  856. /** Obtain the root port from other thread.
  857. *
  858. * @param root pointer to root object
  859. *
  860. * @retval 0 if successful
  861. * @retval -1 upon an error
  862. *
  863. * @ERRORS
  864. * @ERROR EFAULT
  865. * @NEW_1_12_7
  866. */
  867. int su_root_obtain(su_root_t *root)
  868. {
  869. if (root == NULL || root->sur_port == NULL)
  870. return (void)(errno = EFAULT), -1;
  871. return su_port_obtain(root->sur_port);
  872. }
  873. /**Check if a thread has obtained the root.
  874. *
  875. * @param root a pointer to root object
  876. *
  877. * @retval 2 if current thread has obtained the root
  878. * @retval 1 if an another thread has obtained the root
  879. * @retval 0 if no thread has obtained the root
  880. * @retval -1 upon an error
  881. *
  882. * @NEW_1_12_7
  883. */
  884. int su_root_has_thread(su_root_t *root)
  885. {
  886. if (root == NULL || root->sur_port == NULL)
  887. return (void)(errno = EFAULT), -1;
  888. return su_port_has_thread(root->sur_port);
  889. }
  890. /* =========================================================================
  891. * Messages
  892. */
  893. /**
  894. * Allocate a su message of given size.
  895. *
  896. * Allocate a su message with given data size.
  897. *
  898. * @param rmsg handle to the new message (may be uninitialized prior calling)
  899. * @param size size of the message data
  900. *
  901. * @retval 0 if successful,
  902. * @retval -1 if message allocation fails.
  903. *
  904. * @NEW_1_12_8
  905. */
  906. int su_msg_new(su_msg_r rmsg, size_t size)
  907. {
  908. su_msg_t *msg;
  909. size_t total = sizeof(*msg) + (size_t)size;
  910. *rmsg = msg = su_zalloc(NULL, (isize_t)total);
  911. if (!*rmsg)
  912. return -1;
  913. msg->sum_size = total;
  914. return 0;
  915. }
  916. /**
  917. * Allocates a message of given size.
  918. *
  919. * The function @c su_msg_create() allocates a message with given data size.
  920. * If successful, it moves the new message handle to the @c rmsg.
  921. *
  922. * @param rmsg handle to the new message (may be uninitialized prior calling)
  923. * @param to the recipient task
  924. * @param from the sender task
  925. * @param wakeup function that is called when message is delivered
  926. * @param size size of the message data
  927. *
  928. * @retval 0 if successful,
  929. * @retval -1 if message allocation fails.
  930. */
  931. int su_msg_create(su_msg_r rmsg,
  932. su_task_r const to,
  933. su_task_r const from,
  934. su_msg_f wakeup,
  935. isize_t size)
  936. {
  937. if (su_msg_new(rmsg, (size_t) size) == 0) {
  938. SU_TASK_COPY(rmsg[0]->sum_to, to, su_msg_create);
  939. SU_TASK_COPY(rmsg[0]->sum_from, from, su_msg_create);
  940. rmsg[0]->sum_func = wakeup;
  941. return 0;
  942. }
  943. return -1;
  944. }
  945. /** Add a delivery report function to a message.
  946. *
  947. * The delivery report funcgtion gets called by the sending task after the
  948. * message was delivered and the message function was executed. (The
  949. * su_root_t message delivery loop calls su_msg_delivery_report()
  950. *
  951. */
  952. int su_msg_report(su_msg_r msg,
  953. su_msg_f report)
  954. {
  955. if (msg && msg[0] && msg[0]->sum_report == NULL) {
  956. msg[0]->sum_report = report;
  957. return 0;
  958. }
  959. return -1;
  960. }
  961. /** Add a deinitializer function to a message.
  962. *
  963. * The deinitializer function is called when the message gets destroyed. It
  964. * is called even if the message was never delivered. Note that the thread
  965. * destroying the message and calling the deinit function is not necessarily
  966. * the same that sent the message nor the original recipient.
  967. *
  968. * @param rmsg message reference
  969. * @param deinit pointer to deinitializer function
  970. *
  971. * @NEW_1_12_8
  972. */
  973. int su_msg_deinitializer(su_msg_r rmsg,
  974. su_msg_deinit_function *deinit)
  975. {
  976. if (rmsg && rmsg[0]) {
  977. rmsg[0]->sum_deinit = deinit;
  978. return 0;
  979. }
  980. return -1;
  981. }
  982. /**
  983. * Allocates a reply message of given size.
  984. *
  985. * @param reply handle to the new message (may be uninitialized prior calling)
  986. * @param rmsg the incoming message
  987. * @param wakeup function that is called when message is delivered
  988. * @param size size of the message data
  989. *
  990. * @retval 0 if successful,
  991. * @retval -1 otherwise.
  992. */
  993. int su_msg_reply(su_msg_r reply, su_msg_cr rmsg,
  994. su_msg_f wakeup, isize_t size)
  995. {
  996. su_msg_r rmsg0;
  997. assert(rmsg != reply);
  998. *rmsg0 = *(su_msg_t **) rmsg;
  999. *reply = NULL;
  1000. return su_msg_create(reply, su_msg_from(rmsg0), su_msg_to(rmsg0), wakeup, size);
  1001. }
  1002. /** Send a delivery report.
  1003. *
  1004. * If the sender has attached a delivery report function to message with
  1005. * su_msg_report(), the message is returned to the message queue of the
  1006. * sending task. The sending task calls the delivery report function when it
  1007. * has received the message.
  1008. */
  1009. void su_msg_delivery_report(su_msg_r rmsg)
  1010. {
  1011. su_task_r swap;
  1012. if (!rmsg || !rmsg[0])
  1013. return;
  1014. if (!rmsg[0]->sum_report) {
  1015. su_msg_destroy(rmsg);
  1016. return;
  1017. }
  1018. *swap = *rmsg[0]->sum_from;
  1019. *rmsg[0]->sum_from = *rmsg[0]->sum_to;
  1020. *rmsg[0]->sum_to = *swap;
  1021. rmsg[0]->sum_func = rmsg[0]->sum_report;
  1022. rmsg[0]->sum_report = NULL;
  1023. su_msg_send(rmsg);
  1024. }
  1025. /** Save a message. */
  1026. void su_msg_save(su_msg_r save, su_msg_r rmsg)
  1027. {
  1028. if (save) {
  1029. if (rmsg)
  1030. save[0] = rmsg[0];
  1031. else
  1032. save[0] = NULL;
  1033. }
  1034. if (rmsg)
  1035. rmsg[0] = NULL;
  1036. }
  1037. /**
  1038. * Destroys an unsent message.
  1039. *
  1040. * @param rmsg message handle.
  1041. */
  1042. void su_msg_destroy(su_msg_r rmsg)
  1043. {
  1044. su_msg_t *msg;
  1045. assert(rmsg);
  1046. msg = rmsg[0], rmsg[0] = NULL;
  1047. if (msg) {
  1048. SU_TASK_ZAP(msg->sum_to, su_msg_destroy);
  1049. SU_TASK_ZAP(msg->sum_from, su_msg_destroy);
  1050. if (msg->sum_deinit)
  1051. msg->sum_deinit(msg->sum_data);
  1052. su_free(NULL, msg);
  1053. }
  1054. }
  1055. /** Gets a pointer to the message data area.
  1056. *
  1057. * The function @c su_msg_data() returns a pointer to the message data
  1058. * area. If @c rmsg contains a @c NULL handle, or message size is 0, @c NULL
  1059. * pointer is returned.
  1060. *
  1061. * @param rmsg message handle
  1062. *
  1063. * @return A pointer to the message data area is returned.
  1064. */
  1065. su_msg_arg_t *su_msg_data(su_msg_cr rmsg)
  1066. {
  1067. if (rmsg[0] && rmsg[0]->sum_size > sizeof(su_msg_t))
  1068. return rmsg[0]->sum_data;
  1069. else
  1070. return NULL;
  1071. }
  1072. /** Get size of message data area. */
  1073. isize_t su_msg_size(su_msg_cr rmsg)
  1074. {
  1075. return rmsg[0] ? rmsg[0]->sum_size - sizeof(su_msg_t) : 0;
  1076. }
  1077. /** Get sending task.
  1078. *
  1079. * Returns the task handle belonging to the sender of the message.
  1080. *
  1081. * If the message handle contains NULL the function @c su_msg_from
  1082. * returns NULL.
  1083. *
  1084. * @param rmsg message handle
  1085. *
  1086. * @return The task handle of the sender is returned.
  1087. */
  1088. _su_task_r su_msg_from(su_msg_cr rmsg)
  1089. {
  1090. return rmsg[0] ? rmsg[0]->sum_from : NULL;
  1091. }
  1092. /** Get destination task.
  1093. *
  1094. * The function @c su_msg_from returns the task handle belonging to the
  1095. * recipient of the message.
  1096. *
  1097. * If the message handle contains NULL the function @c su_msg_to
  1098. * returns NULL.
  1099. *
  1100. * @param rmsg message handle
  1101. *
  1102. * @return The task handle of the recipient is returned.
  1103. */
  1104. _su_task_r su_msg_to(su_msg_cr rmsg)
  1105. {
  1106. return rmsg[0] ? rmsg[0]->sum_to : NULL;
  1107. }
  1108. /** Remove references to 'from' and 'to' tasks from a message.
  1109. *
  1110. * @param rmsg message handle
  1111. */
  1112. void su_msg_remove_refs(su_msg_cr rmsg)
  1113. {
  1114. if (rmsg[0]) {
  1115. su_task_deinit(rmsg[0]->sum_to);
  1116. su_task_deinit(rmsg[0]->sum_from);
  1117. }
  1118. }
  1119. /**Send a message.
  1120. *
  1121. * The function @c su_msg_send() sends the message. The message is added to
  1122. * the recipients message queue, and recipient is waken up. The caller may
  1123. * not alter the message or the data associated with it after the message
  1124. * has been sent.
  1125. *
  1126. * @param rmsg message handle
  1127. *
  1128. * @retval 0 if signal was sent successfully or handle was @c NULL,
  1129. * @retval -1 otherwise.
  1130. */
  1131. int su_msg_send(su_msg_r rmsg)
  1132. {
  1133. assert(rmsg);
  1134. if (rmsg[0]) {
  1135. su_msg_t *msg = rmsg[0];
  1136. if (msg->sum_to->sut_port)
  1137. return su_port_send(msg->sum_to->sut_port, rmsg);
  1138. su_msg_destroy(rmsg);
  1139. errno = EINVAL;
  1140. return -1;
  1141. }
  1142. return 0;
  1143. }
  1144. /** Send message to the @a to_task and mark @a from_task as sender.
  1145. *
  1146. * @NEW_1_12_8
  1147. */
  1148. SOFIAPUBFUN int su_msg_send_to(su_msg_r rmsg,
  1149. su_task_r const to_task,
  1150. su_msg_f wakeup)
  1151. {
  1152. assert(rmsg); assert(to_task);
  1153. if (rmsg[0]) {
  1154. su_msg_t *msg = rmsg[0];
  1155. if (wakeup)
  1156. msg->sum_func = wakeup;
  1157. if (msg->sum_to->sut_port &&
  1158. msg->sum_to->sut_port != to_task->sut_port) {
  1159. SU_TASK_ZAP(msg->sum_to, "su_msg_send_to");
  1160. }
  1161. if (to_task->sut_port != NULL) {
  1162. msg->sum_to->sut_port = NULL;
  1163. msg->sum_to->sut_root = to_task->sut_root;
  1164. return su_port_send(to_task->sut_port, rmsg);
  1165. }
  1166. su_msg_destroy(rmsg);
  1167. errno = EINVAL;
  1168. return -1;
  1169. }
  1170. return 0;
  1171. }