su
1.12.11
|
00001 /* 00002 * This file is part of the Sofia-SIP package 00003 * 00004 * Copyright (C) 2005 Nokia Corporation. 00005 * 00006 * Contact: Pekka Pessi <pekka.pessi@nokia-email.address.hidden> 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public License 00010 * as published by the Free Software Foundation; either version 2.1 of 00011 * the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 00021 * 02110-1301 USA 00022 * 00023 */ 00024 00025 #ifndef SU_PORT_H 00026 00027 #define SU_PORT_H 00028 00040 #ifndef SU_MSG_ARG_T 00041 #define SU_MSG_ARG_T union { char anoymous[4]; } 00042 #endif 00043 00044 #ifndef SU_WAIT_H 00045 #include "sofia-sip/su_wait.h" 00046 #endif 00047 00048 #ifndef SU_MODULE_DEBUG_H 00049 #include "su_module_debug.h" 00050 #endif 00051 00052 #ifndef SU_ALLOC_H 00053 #include <sofia-sip/su_alloc.h> 00054 #endif 00055 00056 #include <assert.h> 00057 00058 #define SU_WAIT_MIN (16) 00059 00060 SOFIA_BEGIN_DECLS 00061 00063 struct su_msg_s { 00064 size_t sum_size; 00065 su_msg_t *sum_next; 00066 su_task_r sum_to; 00067 su_task_r sum_from; 00068 su_msg_f sum_func; 00069 su_msg_f sum_report; 00070 su_msg_deinit_function *sum_deinit; 00071 su_msg_arg_t sum_data[1]; /* minimum size, may be extended */ 00072 }; 00073 00074 struct _GSource; 00075 00077 struct su_root_s { 00078 int sur_size; 00079 su_root_magic_t *sur_magic; 00080 su_root_deinit_f sur_deinit; 00081 su_task_r sur_task; 00082 su_task_r sur_parent; 00083 unsigned sur_threading : 1; 00084 unsigned sur_deiniting : 1; 00085 }; 00086 00087 #define SU_ROOT_MAGIC(r) ((r) ? (r)->sur_magic : NULL) 00088 00089 enum su_port_thread_op { 00090 su_port_thread_op_is_obtained, 00091 su_port_thread_op_release, 00092 su_port_thread_op_obtain 00093 }; 00094 00096 typedef struct su_port_vtable { 00097 unsigned su_vtable_size; 00098 void (*su_port_lock)(su_port_t *port, char const *who); 00099 void (*su_port_unlock)(su_port_t *port, char const *who); 00100 void (*su_port_incref)(su_port_t *port, char const *who); 00101 void (*su_port_decref)(su_port_t *port, int block, char const *who); 00102 struct _GSource *(*su_port_gsource)(su_port_t *port); 00103 int (*su_port_send)(su_port_t *self, su_msg_r rmsg); 00104 int (*su_port_register)(su_port_t *self, 00105 su_root_t *root, 00106 su_wait_t *wait, 00107 su_wakeup_f callback, 00108 su_wakeup_arg_t *arg, 00109 int priority); 00110 int (*su_port_unregister)(su_port_t *port, 00111 su_root_t *root, 00112 su_wait_t *wait, 00113 su_wakeup_f callback, 00114 su_wakeup_arg_t *arg); 00115 int (*su_port_deregister)(su_port_t *self, int i); 00116 int (*su_port_unregister_all)(su_port_t *self, 00117 su_root_t *root); 00118 int (*su_port_eventmask)(su_port_t *self, int index, int socket, int events); 00119 void (*su_port_run)(su_port_t *self); 00120 void (*su_port_break)(su_port_t *self); 00121 su_duration_t (*su_port_step)(su_port_t *self, su_duration_t tout); 00122 00123 /* Reused slot */ 00124 int (*su_port_thread)(su_port_t *port, enum su_port_thread_op op); 00125 00126 int (*su_port_add_prepoll)(su_port_t *port, 00127 su_root_t *root, 00128 su_prepoll_f *, 00129 su_prepoll_magic_t *); 00130 00131 int (*su_port_remove_prepoll)(su_port_t *port, 00132 su_root_t *root); 00133 00134 su_timer_queue_t *(*su_port_timers)(su_port_t *port); 00135 00136 int (*su_port_multishot)(su_port_t *port, int multishot); 00137 00138 /* Extension from >= 1.12.4 */ 00139 int (*su_port_wait_events)(su_port_t *port, su_duration_t timeout); 00140 int (*su_port_getmsgs)(su_port_t *port); 00141 /* Extension from >= 1.12.5 */ 00142 int (*su_port_getmsgs_from)(su_port_t *port, su_port_t *cloneport); 00143 char const *(*su_port_name)(su_port_t const *port); 00144 int (*su_port_start_shared)(su_root_t *root, 00145 su_clone_r return_clone, 00146 su_root_magic_t *magic, 00147 su_root_init_f init, 00148 su_root_deinit_f deinit); 00149 void (*su_port_wait)(su_clone_r rclone); 00150 int (*su_port_execute)(su_task_r const task, 00151 int (*function)(void *), void *arg, 00152 int *return_value); 00153 00154 /* >= 1.12.11 */ 00155 su_timer_queue_t *(*su_port_deferrable)(su_port_t *port); 00156 int (*su_port_max_defer)(su_port_t *port, 00157 su_duration_t *return_duration, 00158 su_duration_t *set_duration); 00159 int (*su_port_wakeup)(su_port_t *port); 00160 int (*su_port_is_running)(su_port_t const *port); 00161 } su_port_vtable_t; 00162 00163 SOFIAPUBFUN su_port_t *su_port_create(void) 00164 __attribute__((__malloc__)); 00165 00166 /* Extension from >= 1.12.5 */ 00167 00168 SOFIAPUBFUN void su_msg_delivery_report(su_msg_r msg); 00169 SOFIAPUBFUN su_duration_t su_timer_next_expires(su_timer_queue_t const *timers, 00170 su_time_t now); 00171 SOFIAPUBFUN su_root_t *su_root_create_with_port(su_root_magic_t *magic, 00172 su_port_t *port) 00173 __attribute__((__malloc__)); 00174 00175 /* Extension from >= 1.12.6 */ 00176 00177 SOFIAPUBFUN char const *su_port_name(su_port_t const *port); 00178 00179 SOFIAPUBFUN int su_timer_reset_all(su_timer_queue_t *, su_task_r ); 00180 00181 /* ---------------------------------------------------------------------- */ 00182 00183 /* React to multiple events per one poll() to make sure 00184 * that high-priority events can never completely mask other events. 00185 * Enabled by default on all platforms except WIN32 */ 00186 #if !defined(WIN32) 00187 #define SU_ENABLE_MULTISHOT_POLL 1 00188 #else 00189 #define SU_ENABLE_MULTISHOT_POLL 0 00190 #endif 00191 00192 /* ---------------------------------------------------------------------- */ 00193 /* Virtual functions */ 00194 00195 typedef struct su_virtual_port_s { 00196 su_home_t sup_home[1]; 00197 su_port_vtable_t const *sup_vtable; 00198 } su_virtual_port_t; 00199 00200 su_inline 00201 su_home_t *su_port_home(su_port_t const *self) 00202 { 00203 return (su_home_t *)self; 00204 } 00205 00206 su_inline 00207 void su_port_lock(su_port_t *self, char const *who) 00208 { 00209 su_virtual_port_t *base = (su_virtual_port_t *)self; 00210 base->sup_vtable->su_port_lock(self, who); 00211 } 00212 00213 su_inline 00214 void su_port_unlock(su_port_t *self, char const *who) 00215 { 00216 su_virtual_port_t *base = (su_virtual_port_t *)self; 00217 base->sup_vtable->su_port_unlock(self, who); 00218 } 00219 00220 su_inline 00221 void su_port_incref(su_port_t *self, char const *who) 00222 { 00223 su_virtual_port_t *base = (su_virtual_port_t *)self; 00224 base->sup_vtable->su_port_incref(self, who); 00225 } 00226 00227 su_inline 00228 void su_port_decref(su_port_t *self, char const *who) 00229 { 00230 su_virtual_port_t *base = (su_virtual_port_t *)self; 00231 base->sup_vtable->su_port_decref(self, 0, who); 00232 } 00233 00234 su_inline 00235 void su_port_zapref(su_port_t *self, char const *who) 00236 { 00237 su_virtual_port_t *base = (su_virtual_port_t *)self; 00238 base->sup_vtable->su_port_decref(self, 1, who); 00239 } 00240 00241 su_inline 00242 struct _GSource *su_port_gsource(su_port_t *self) 00243 { 00244 su_virtual_port_t *base = (su_virtual_port_t *)self; 00245 return base->sup_vtable->su_port_gsource(self); 00246 } 00247 00248 su_inline 00249 int su_port_send(su_port_t *self, su_msg_r rmsg) 00250 { 00251 su_virtual_port_t *base = (su_virtual_port_t *)self; 00252 return base->sup_vtable->su_port_send(self, rmsg); 00253 } 00254 00255 su_inline 00256 int su_port_wakeup(su_port_t *self) 00257 { 00258 su_virtual_port_t *base = (su_virtual_port_t *)self; 00259 return base->sup_vtable->su_port_wakeup(self); 00260 } 00261 00262 su_inline 00263 int su_port_register(su_port_t *self, 00264 su_root_t *root, 00265 su_wait_t *wait, 00266 su_wakeup_f callback, 00267 su_wakeup_arg_t *arg, 00268 int priority) 00269 { 00270 su_virtual_port_t *base = (su_virtual_port_t *)self; 00271 return base->sup_vtable-> 00272 su_port_register(self, root, wait, callback, arg, priority); 00273 } 00274 00275 su_inline 00276 int su_port_unregister(su_port_t *self, 00277 su_root_t *root, 00278 su_wait_t *wait, 00279 su_wakeup_f callback, 00280 su_wakeup_arg_t *arg) 00281 { 00282 su_virtual_port_t *base = (su_virtual_port_t *)self; 00283 return base->sup_vtable-> 00284 su_port_unregister(self, root, wait, callback, arg); 00285 } 00286 00287 su_inline 00288 int su_port_deregister(su_port_t *self, int i) 00289 { 00290 su_virtual_port_t *base = (su_virtual_port_t *)self; 00291 return base->sup_vtable-> 00292 su_port_deregister(self, i); 00293 } 00294 00295 su_inline 00296 int su_port_unregister_all(su_port_t *self, 00297 su_root_t *root) 00298 { 00299 su_virtual_port_t *base = (su_virtual_port_t *)self; 00300 return base->sup_vtable-> 00301 su_port_unregister_all(self, root); 00302 } 00303 00304 su_inline 00305 int su_port_eventmask(su_port_t *self, int index, int socket, int events) 00306 { 00307 su_virtual_port_t *base = (su_virtual_port_t *)self; 00308 return base->sup_vtable-> 00309 su_port_eventmask(self, index, socket, events); 00310 } 00311 00312 su_inline 00313 int su_port_wait_events(su_port_t *self, su_duration_t timeout) 00314 { 00315 su_virtual_port_t *base = (su_virtual_port_t *)self; 00316 if (base->sup_vtable->su_port_wait_events == NULL) 00317 return errno = ENOSYS, -1; 00318 return base->sup_vtable-> 00319 su_port_wait_events(self, timeout); 00320 } 00321 00322 su_inline 00323 void su_port_run(su_port_t *self) 00324 { 00325 su_virtual_port_t *base = (su_virtual_port_t *)self; 00326 base->sup_vtable->su_port_run(self); 00327 } 00328 00329 su_inline 00330 void su_port_break(su_port_t *self) 00331 { 00332 su_virtual_port_t *base = (su_virtual_port_t *)self; 00333 base->sup_vtable->su_port_break(self); 00334 } 00335 00336 su_inline 00337 su_duration_t su_port_step(su_port_t *self, su_duration_t tout) 00338 { 00339 su_virtual_port_t *base = (su_virtual_port_t *)self; 00340 return base->sup_vtable->su_port_step(self, tout); 00341 } 00342 00343 00344 su_inline 00345 int su_port_own_thread(su_port_t const *self) 00346 { 00347 su_virtual_port_t const *base = (su_virtual_port_t *)self; 00348 return base->sup_vtable-> 00349 su_port_thread((su_port_t *)self, su_port_thread_op_is_obtained) == 2; 00350 } 00351 00352 su_inline int su_port_has_thread(su_port_t *self) 00353 { 00354 su_virtual_port_t *base = (su_virtual_port_t *)self; 00355 return base->sup_vtable->su_port_thread(self, su_port_thread_op_is_obtained); 00356 } 00357 00358 su_inline int su_port_release(su_port_t *self) 00359 { 00360 su_virtual_port_t *base = (su_virtual_port_t *)self; 00361 return base->sup_vtable->su_port_thread(self, su_port_thread_op_release); 00362 } 00363 00364 su_inline int su_port_obtain(su_port_t *self) 00365 { 00366 su_virtual_port_t *base = (su_virtual_port_t *)self; 00367 return base->sup_vtable->su_port_thread(self, su_port_thread_op_obtain); 00368 } 00369 00370 su_inline 00371 int su_port_add_prepoll(su_port_t *self, 00372 su_root_t *root, 00373 su_prepoll_f *prepoll, 00374 su_prepoll_magic_t *magic) 00375 { 00376 su_virtual_port_t *base = (su_virtual_port_t *)self; 00377 return base->sup_vtable->su_port_add_prepoll(self, root, prepoll, magic); 00378 } 00379 00380 su_inline 00381 int su_port_remove_prepoll(su_port_t *self, 00382 su_root_t *root) 00383 { 00384 su_virtual_port_t *base = (su_virtual_port_t *)self; 00385 return base->sup_vtable->su_port_remove_prepoll(self, root); 00386 } 00387 00388 su_inline 00389 su_timer_queue_t *su_port_timers(su_port_t *self) 00390 { 00391 su_virtual_port_t *base = (su_virtual_port_t *)self; 00392 return base->sup_vtable->su_port_timers(self); 00393 } 00394 00395 su_inline 00396 int su_port_multishot(su_port_t *self, int multishot) 00397 { 00398 su_virtual_port_t *base = (su_virtual_port_t *)self; 00399 return base->sup_vtable->su_port_multishot(self, multishot); 00400 } 00401 00402 su_inline 00403 int su_port_getmsgs(su_port_t *self) 00404 { 00405 su_virtual_port_t *base = (su_virtual_port_t *)self; 00406 return base->sup_vtable->su_port_getmsgs(self); 00407 } 00408 00409 su_inline 00410 int su_port_getmsgs_from(su_port_t *self, su_port_t *cloneport) 00411 { 00412 su_virtual_port_t *base = (su_virtual_port_t *)self; 00413 return base->sup_vtable->su_port_getmsgs_from(self, cloneport); 00414 } 00415 00418 su_inline 00419 su_timer_queue_t *su_port_deferrable(su_port_t *self) 00420 { 00421 su_virtual_port_t *base = (su_virtual_port_t *)self; 00422 00423 if (base == NULL) { 00424 errno = EFAULT; 00425 return NULL; 00426 } 00427 00428 return base->sup_vtable->su_port_deferrable(self); 00429 } 00430 00431 su_inline 00432 int su_port_max_defer(su_port_t *self, 00433 su_duration_t *return_duration, 00434 su_duration_t *set_duration) 00435 { 00436 su_virtual_port_t *base = (su_virtual_port_t *)self; 00437 00438 if (base == NULL) 00439 return (errno = EFAULT), -1; 00440 00441 return base->sup_vtable->su_port_max_defer(self, 00442 return_duration, 00443 set_duration); 00444 } 00445 00446 su_inline 00447 int su_port_is_running(su_port_t const *self) 00448 { 00449 su_virtual_port_t *base = (su_virtual_port_t *)self; 00450 return base && base->sup_vtable->su_port_is_running(self); 00451 } 00452 00453 SOFIAPUBFUN void su_port_wait(su_clone_r rclone); 00454 00455 SOFIAPUBFUN int su_port_execute(su_task_r const task, 00456 int (*function)(void *), void *arg, 00457 int *return_value); 00458 00459 /* ---------------------------------------------------------------------- */ 00460 00466 typedef struct su_base_port_s { 00467 su_home_t sup_home[1]; 00468 su_port_vtable_t const *sup_vtable; 00469 00470 /* Implementation may vary stuff below, too. */ 00471 00472 /* Pre-poll callback */ 00473 su_prepoll_f *sup_prepoll; 00474 su_prepoll_magic_t *sup_pp_magic; 00475 su_root_t *sup_pp_root; 00476 00477 /* Message list - this is protected by su_port_lock()/su_port_unlock() */ 00478 su_msg_t *sup_head, **sup_tail; 00479 00480 /* Timer list */ 00481 su_timer_queue_t sup_timers, sup_deferrable; 00482 00483 su_duration_t sup_max_defer; 00485 unsigned sup_running; 00486 } su_base_port_t; 00487 00488 /* Base methods */ 00489 00490 SOFIAPUBFUN int su_base_port_init(su_port_t *, su_port_vtable_t const *); 00491 SOFIAPUBFUN void su_base_port_deinit(su_port_t *self); 00492 00493 SOFIAPUBFUN void su_base_port_lock(su_port_t *self, char const *who); 00494 SOFIAPUBFUN void su_base_port_unlock(su_port_t *self, char const *who); 00495 00496 SOFIAPUBFUN int su_base_port_thread(su_port_t const *self, 00497 enum su_port_thread_op op); 00498 00499 SOFIAPUBFUN void su_base_port_incref(su_port_t *self, char const *who); 00500 SOFIAPUBFUN int su_base_port_decref(su_port_t *self, 00501 int blocking, 00502 char const *who); 00503 00504 SOFIAPUBFUN struct _GSource *su_base_port_gsource(su_port_t *self); 00505 00506 SOFIAPUBFUN su_socket_t su_base_port_mbox(su_port_t *self); 00507 SOFIAPUBFUN int su_base_port_send(su_port_t *self, su_msg_r rmsg); 00508 SOFIAPUBFUN int su_base_port_getmsgs(su_port_t *self); 00509 SOFIAPUBFUN int su_base_port_getmsgs_from(su_port_t *self, 00510 su_port_t *from); 00511 00512 SOFIAPUBFUN void su_base_port_run(su_port_t *self); 00513 SOFIAPUBFUN void su_base_port_break(su_port_t *self); 00514 SOFIAPUBFUN su_duration_t su_base_port_step(su_port_t *self, 00515 su_duration_t tout); 00516 00517 SOFIAPUBFUN int su_base_port_add_prepoll(su_port_t *self, 00518 su_root_t *root, 00519 su_prepoll_f *, 00520 su_prepoll_magic_t *); 00521 00522 SOFIAPUBFUN int su_base_port_remove_prepoll(su_port_t *self, su_root_t *root); 00523 00524 SOFIAPUBFUN su_timer_queue_t *su_base_port_timers(su_port_t *self); 00525 00526 SOFIAPUBFUN int su_base_port_multishot(su_port_t *self, int multishot); 00527 00528 SOFIAPUBFUN int su_base_port_start_shared(su_root_t *parent, 00529 su_clone_r return_clone, 00530 su_root_magic_t *magic, 00531 su_root_init_f init, 00532 su_root_deinit_f deinit); 00533 SOFIAPUBFUN void su_base_port_wait(su_clone_r rclone); 00534 00535 SOFIAPUBFUN su_timer_queue_t *su_base_port_deferrable(su_port_t *self); 00536 00537 SOFIAPUBFUN int su_base_port_max_defer(su_port_t *self, 00538 su_duration_t *return_duration, 00539 su_duration_t *set_duration); 00540 00541 SOFIAPUBFUN int su_base_port_is_running(su_port_t const *self); 00542 00543 /* ---------------------------------------------------------------------- */ 00544 00545 #if SU_HAVE_PTHREADS 00546 00547 #include <pthread.h> 00548 00550 typedef struct su_pthread_port_s { 00551 su_base_port_t sup_base[1]; 00552 struct su_pthread_port_waiting_parent 00553 *sup_waiting_parent; 00554 pthread_t sup_tid; 00555 pthread_mutex_t sup_obtained[1]; 00556 00557 #if 0 /* Pausing and resuming are not used */ 00558 pthread_mutex_t sup_runlock[1]; 00559 pthread_cond_t sup_resume[1]; 00560 short sup_paused; 00561 #endif 00562 short sup_thread; 00563 } su_pthread_port_t; 00564 00565 /* Pthread methods */ 00566 00567 SOFIAPUBFUN int su_pthread_port_init(su_port_t *, su_port_vtable_t const *); 00568 SOFIAPUBFUN void su_pthread_port_deinit(su_port_t *self); 00569 00570 SOFIAPUBFUN void su_pthread_port_lock(su_port_t *self, char const *who); 00571 SOFIAPUBFUN void su_pthread_port_unlock(su_port_t *self, char const *who); 00572 00573 SOFIAPUBFUN int su_pthread_port_thread(su_port_t *self, 00574 enum su_port_thread_op op); 00575 00576 #if 0 /* not yet */ 00577 SOFIAPUBFUN int su_pthread_port_send(su_port_t *self, su_msg_r rmsg); 00578 00579 SOFIAPUBFUN su_port_t *su_pthread_port_create(void); 00580 SOFIAPUBFUN su_port_t *su_pthread_port_start(su_root_t *parent, 00581 su_clone_r return_clone, 00582 su_root_magic_t *magic, 00583 su_root_init_f init, 00584 su_root_deinit_f deinit); 00585 #endif 00586 00587 SOFIAPUBFUN int su_pthreaded_port_start(su_port_create_f *create, 00588 su_root_t *parent, 00589 su_clone_r return_clone, 00590 su_root_magic_t *magic, 00591 su_root_init_f init, 00592 su_root_deinit_f deinit); 00593 00594 SOFIAPUBFUN void su_pthread_port_wait(su_clone_r rclone); 00595 SOFIAPUBFUN int su_pthread_port_execute(su_task_r const task, 00596 int (*function)(void *), void *arg, 00597 int *return_value); 00598 00599 #if 0 00600 SOFIAPUBFUN int su_pthread_port_pause(su_port_t *self); 00601 SOFIAPUBFUN int su_pthread_port_resume(su_port_t *self); 00602 #endif 00603 00604 #else 00605 00606 typedef su_base_port_t su_pthread_port_t; 00607 00608 #define su_pthread_port_init su_base_port_init 00609 #define su_pthread_port_deinit su_base_port_deinit 00610 #define su_pthread_port_lock su_base_port_lock 00611 #define su_pthread_port_unlock su_base_port_unlock 00612 #define su_pthread_port_thread su_base_port_thread 00613 #define su_pthread_port_wait su_base_port_wait 00614 #define su_pthread_port_execute su_base_port_execute 00615 00616 #endif 00617 00618 /* ====================================================================== */ 00619 /* Mailbox port using sockets */ 00620 00621 #define SU_MBOX_SIZE 2 00622 00623 typedef struct su_socket_port_s { 00624 su_pthread_port_t sup_base[1]; 00625 int sup_mbox_index; 00626 su_socket_t sup_mbox[SU_MBOX_SIZE]; 00627 } su_socket_port_t; 00628 00629 SOFIAPUBFUN int su_socket_port_init(su_socket_port_t *, 00630 su_port_vtable_t const *); 00631 SOFIAPUBFUN void su_socket_port_deinit(su_socket_port_t *self); 00632 SOFIAPUBFUN int su_socket_port_send(su_port_t *self, su_msg_r rmsg); 00633 SOFIAPUBFUN int su_socket_port_wakeup(su_port_t *self); 00634 00635 SOFIA_END_DECLS 00636 00637 #endif /* SU_PORT_H */