#include "gw-config.h"#include <sys/poll.h>Include dependency graph for gwthread.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Defines | |
| #define | MAIN_THREAD_ID 0 |
| #define | gwthread_create(func, arg) (gwthread_create_real(func, __FILE__ ":" #func, arg)) |
Typedefs | |
| typedef void | gwthread_func_t (void *arg) |
Functions | |
| void | gwthread_init (void) |
| void | gwthread_shutdown (void) |
| long | gwthread_create_real (gwthread_func_t *func, const char *funcname, void *arg) |
| void | gwthread_join (long thread) |
| void | gwthread_join_every (gwthread_func_t *func) |
| void | gwthread_join_all (void) |
| long | gwthread_self (void) |
| long | gwthread_self_pid (void) |
| void | gwthread_self_ids (long *tid, long *pid) |
| void | gwthread_wakeup (long thread) |
| void | gwthread_wakeup_all (void) |
| int | gwthread_pollfd (int fd, int events, double timeout) |
| int | gwthread_poll (struct pollfd *fds, long numfds, double timeout) |
| void | gwthread_sleep (double seconds) |
| void | gwthread_sleep_micro (double dseconds) |
| int | gwthread_cancel (long thread) |
| int | gwthread_shouldhandlesignal (int signal) |
| int | gwthread_dumpsigmask (void) |
|
|
|
Definition at line 75 of file gwthread.h. Referenced by httpd_shutdown(), sms_router(), smsboxc_run(), udp_receiver(), and wapboxc_run(). |
|
|
Definition at line 77 of file gwthread.h. |
|
|
Definition at line 819 of file gwthread-pthread.c. References gw_assert, threadinfo::number, threadinfo::self, and THREAD. Referenced by main(). 00820 {
00821 struct threadinfo *threadinfo;
00822
00823 gw_assert(thread >= 0);
00824
00825 threadinfo = THREAD(thread);
00826 if (threadinfo == NULL || threadinfo->number != thread) {
00827 return -1;
00828 } else {
00829 return pthread_cancel(threadinfo->self);
00830 }
00831 }
|
|
||||||||||||||||
|
Definition at line 488 of file gwthread-pthread.c. References block_user_signals(), gwthread_self(), name, restore_user_signals(), and spawn_thread(). 00489 {
00490 int sigtrick = 0;
00491 sigset_t old_signal_set;
00492 long thread_id;
00493
00494 /*
00495 * We want to make sure that only the main thread handles signals,
00496 * so that each signal is handled exactly once. To do this, we
00497 * make sure that each new thread has all the signals that we
00498 * handle blocked. To avoid race conditions, we block them in
00499 * the spawning thread first, then create the new thread (which
00500 * inherits the settings), and then restore the old settings in
00501 * the spawning thread. This means that there is a brief period
00502 * when no signals will be processed, but during that time they
00503 * should be queued by the operating system.
00504 */
00505 if (gwthread_self() == MAIN_THREAD_ID)
00506 sigtrick = block_user_signals(&old_signal_set) == 0;
00507
00508 thread_id = spawn_thread(func, name, arg);
00509
00510 /*
00511 * Restore the old signal mask. The new thread will have
00512 * inherited the resticted one, but the main thread needs
00513 * the old one back.
00514 */
00515 if (sigtrick)
00516 restore_user_signals(&old_signal_set);
00517
00518 return thread_id;
00519 }
|
Here is the call graph for this function:

|
|
Definition at line 848 of file gwthread-pthread.c. References debug(), and warning(). 00848 {
00849 sigset_t signal_set;
00850 int signum;
00851
00852 /* Grab the signal set data from our thread */
00853 if (pthread_sigmask(SIG_BLOCK, NULL, &signal_set) != 0) {
00854 warning(0, "gwthread_dumpsigmask: Couldn't get signal mask.");
00855 return -1;
00856 }
00857
00858 /* For each signal normally defined (there are usually only 32),
00859 * print a message if we don't block it. */
00860 for (signum = 1; signum <= 32; signum++) {
00861 if (!sigismember(&signal_set, signum)) {
00862 debug("gwlib", 0,
00863 "gwthread_dumpsigmask: Signal Number %d will be caught.",
00864 signum);
00865 }
00866 }
00867 return 0;
00868 }
|
Here is the call graph for this function:

|
|
Definition at line 263 of file gwthread-pthread.c. References active_threads, fill_threadinfo(), mainthread, panic, threadtable, threadtable_lock, and tsd_key. Referenced by gwlib_init(). 00264 {
00265 int ret;
00266 int i;
00267
00268 pthread_mutex_init(&threadtable_lock, NULL);
00269
00270 ret = pthread_key_create(&tsd_key, NULL);
00271 if (ret != 0) {
00272 panic(ret, "gwthread-pthread: pthread_key_create failed");
00273 }
00274
00275 for (i = 0; i < THREADTABLE_SIZE; i++) {
00276 threadtable[i] = NULL;
00277 }
00278 active_threads = 0;
00279
00280 /* create main thread info */
00281 if (fill_threadinfo(pthread_self(), "main", NULL, &mainthread) == -1)
00282 panic(0, "gwthread-pthread: unable to fill main threadinfo.");
00283
00284 ret = pthread_setspecific(tsd_key, &mainthread);
00285 if (ret != 0)
00286 panic(ret, "gwthread-pthread: pthread_setspecific failed");
00287 }
|
Here is the call graph for this function:

|
|
Definition at line 521 of file gwthread-pthread.c. References gw_assert, gwlist_append(), gwlist_create, threadinfo::joiners, lock, threadinfo::number, THREAD, threadtable_lock, unlock, and warning(). Referenced by cimd2_shutdown_cb(), emi2_sender(), fdset_destroy(), gwthread_join_all(), heartbeat_stop(), httpd_emu_destroy(), httpsmsc_send_cb(), main(), oisd_shutdown_cb(), receive_smpp_thread(), run_smsbox(), run_wapbox(), shutdown_cb(), smpp_emu(), smpp_emu_reader(), smsboxc_run(), smsc_cimd2_create(), smsc_emi2_create(), smsc_emu_destroy(), smsc_oisd_create(), smsc_smpp_create(), soap_server_stop(), soap_shutdown_cb(), store_file_shutdown(), timers_shutdown(), udp_sender(), and wrapper_sender(). 00522 {
00523 struct threadinfo *threadinfo;
00524 pthread_cond_t exit_cond;
00525 int ret;
00526
00527 gw_assert(thread >= 0);
00528
00529 lock();
00530 threadinfo = THREAD(thread);
00531 if (threadinfo == NULL || threadinfo->number != thread) {
00532 /* The other thread has already exited */
00533 unlock();
00534 return;
00535 }
00536
00537 /* Register our desire to be alerted when that thread exits,
00538 * and wait for it. */
00539
00540 ret = pthread_cond_init(&exit_cond, NULL);
00541 if (ret != 0) {
00542 warning(ret, "gwthread_join: cannot create condition variable.");
00543 unlock();
00544 return;
00545 }
00546
00547 if (!threadinfo->joiners)
00548 threadinfo->joiners = gwlist_create();
00549 gwlist_append(threadinfo->joiners, &exit_cond);
00550
00551 /* The wait immediately releases the lock, and reacquires it
00552 * when the condition is satisfied. So don't worry, we're not
00553 * blocking while keeping the table locked. */
00554 ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
00555 unlock();
00556
00557 if (ret != 0)
00558 warning(ret, "gwthread_join: error in pthread_cond_wait");
00559
00560 pthread_cond_destroy(&exit_cond);
00561 }
|
Here is the call graph for this function:

|
|
Definition at line 563 of file gwthread-pthread.c. References gwthread_join(), gwthread_self(), and THREAD. Referenced by main(). 00564 {
00565 long i;
00566 long our_thread = gwthread_self();
00567
00568 for (i = 0; i < THREADTABLE_SIZE; ++i) {
00569 if (THREAD(our_thread) != THREAD(i))
00570 gwthread_join(i);
00571 }
00572 }
|
Here is the call graph for this function:

|
|
Definition at line 585 of file gwthread-pthread.c. References debug(), threadinfo::func, gwlist_append(), gwlist_create, threadinfo::joiners, lock, threadinfo::name, threadinfo::number, THREAD, threadtable_lock, unlock, and warning(). Referenced by client_shutdown(), http_close_all_ports(), httpadmin_stop(), main(), main_for_producer_and_consumer(), radius_acct_shutdown(), server_shutdown(), wap_appl_shutdown(), wap_push_ota_shutdown(), wap_push_ppg_shutdown(), wsp_push_client_shutdown(), wsp_session_shutdown(), wsp_unit_shutdown(), wtp_initiator_shutdown(), and wtp_resp_shutdown(). 00586 {
00587 struct threadinfo *ti;
00588 pthread_cond_t exit_cond;
00589 int ret;
00590 long i;
00591
00592 ret = pthread_cond_init(&exit_cond, NULL);
00593 if (ret != 0) {
00594 warning(ret, "gwthread_join_every: cannot create condition variable.");
00595 unlock();
00596 return;
00597 }
00598
00599 /*
00600 * FIXME: To be really safe, this function should keep looping
00601 * over the table until it does a complete run without having
00602 * to call pthread_cond_wait. Otherwise, new threads could
00603 * start while we wait, and we'll miss them.
00604 */
00605 lock();
00606 for (i = 0; i < THREADTABLE_SIZE; ++i) {
00607 ti = THREAD(i);
00608 if (ti == NULL || ti->func != func)
00609 continue;
00610 debug("gwlib.gwthread", 0,
00611 "Waiting for %ld (%s) to terminate",
00612 ti->number, ti->name);
00613 if (!ti->joiners)
00614 ti->joiners = gwlist_create();
00615 gwlist_append(ti->joiners, &exit_cond);
00616 ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
00617 if (ret != 0)
00618 warning(ret, "gwthread_join_all: error in pthread_cond_wait");
00619 }
00620 unlock();
00621
00622 pthread_cond_destroy(&exit_cond);
00623 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 716 of file gwthread-pthread.c. References error(), pollfd::fd, flushpipe(), getthreadinfo(), poll, and threadinfo::wakefd_recv. Referenced by poller(), and server_thread(). 00717 {
00718 struct pollfd *pollfds;
00719 struct threadinfo *threadinfo;
00720 int milliseconds;
00721 int ret;
00722
00723 threadinfo = getthreadinfo();
00724
00725 /* Create a new pollfd array with an extra element for the
00726 * thread wakeup fd. */
00727
00728 pollfds = gw_malloc((numfds + 1) * sizeof(*pollfds));
00729 pollfds[0].fd = threadinfo->wakefd_recv;
00730 pollfds[0].events = POLLIN;
00731 pollfds[0].revents = 0;
00732 memcpy(pollfds + 1, fds, numfds * sizeof(*pollfds));
00733
00734 milliseconds = timeout * 1000;
00735 if (milliseconds < 0)
00736 milliseconds = POLL_NOTIMEOUT;
00737
00738 ret = poll(pollfds, numfds + 1, milliseconds);
00739 if (ret < 0) {
00740 if (errno != EINTR)
00741 error(errno, "gwthread_poll: error in poll");
00742 gw_free(pollfds);
00743 return -1;
00744 }
00745 if (pollfds[0].revents)
00746 flushpipe(pollfds[0].fd);
00747
00748 /* Copy the results back to the caller */
00749 memcpy(fds, pollfds + 1, numfds * sizeof(*pollfds));
00750 gw_free(pollfds);
00751
00752 return ret;
00753 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 682 of file gwthread-pthread.c. References error(), pollfd::events, pollfd::fd, flushpipe(), getthreadinfo(), poll, pollfd::revents, and threadinfo::wakefd_recv. Referenced by accept_thread(), cgw_listener(), cgw_wait_command(), conn_flush(), conn_wait(), emi2_listener(), fake_listener(), gw_accept(), and wait_for_connections(). 00683 {
00684 struct pollfd pollfd[2];
00685 struct threadinfo *threadinfo;
00686 int milliseconds;
00687 int ret;
00688
00689 threadinfo = getthreadinfo();
00690
00691 pollfd[0].fd = threadinfo->wakefd_recv;
00692 pollfd[0].events = POLLIN;
00693 pollfd[0].revents = 0;
00694
00695 pollfd[1].fd = fd;
00696 pollfd[1].events = events;
00697 pollfd[1].revents = 0;
00698
00699 milliseconds = timeout * 1000;
00700 if (milliseconds < 0)
00701 milliseconds = POLL_NOTIMEOUT;
00702
00703 ret = poll(pollfd, 2, milliseconds);
00704 if (ret < 0) {
00705 if (errno != EINTR)
00706 error(errno, "gwthread_pollfd: error in poll");
00707 return -1;
00708 }
00709
00710 if (pollfd[0].revents)
00711 flushpipe(pollfd[0].fd);
00712
00713 return pollfd[1].revents;
00714 }
|
Here is the call graph for this function:

|
|
Definition at line 626 of file gwthread-pthread.c. 00627 {
00628 struct threadinfo *threadinfo;
00629 threadinfo = pthread_getspecific(tsd_key);
00630 if (threadinfo)
00631 return threadinfo->number;
00632 else
00633 return -1;
00634 }
|
|
||||||||||||
|
Definition at line 647 of file gwthread-pthread.c. References threadinfo::number, threadinfo::pid, tid, and tsd_key. Referenced by format(). 00648 {
00649 struct threadinfo *threadinfo;
00650 threadinfo = pthread_getspecific(tsd_key);
00651 if (threadinfo) {
00652 *tid = threadinfo->number;
00653 *pid = (threadinfo->pid != -1) ? threadinfo->pid : getpid();
00654 } else {
00655 *tid = -1;
00656 *pid = getpid();
00657 }
00658 }
|
|
|
Definition at line 637 of file gwthread-pthread.c. References threadinfo::pid, and tsd_key. 00638 {
00639 struct threadinfo *threadinfo;
00640 threadinfo = pthread_getspecific(tsd_key);
00641 if (threadinfo && threadinfo->pid != -1)
00642 return (long) threadinfo->pid;
00643 else
00644 return (long) getpid();
00645 }
|
|
|
Definition at line 837 of file gwthread-pthread.c. Referenced by signal_handler(). 00837 {
00838 return 1;
00839 }
|
|
|
Definition at line 292 of file gwthread-pthread.c. References debug(), gw_assert, lock, name, number, running, threadtable, threadtable_lock, unlock, and warning(). Referenced by gwlib_shutdown(). 00293 {
00294 int ret;
00295 int running;
00296 int i;
00297
00298 /* Main thread must not have disappeared */
00299 gw_assert(threadtable[0] != NULL);
00300 lock();
00301
00302 running = 0;
00303 /* Start i at 1 to skip the main thread, which is supposed to be
00304 * still running. */
00305 for (i = 1; i < THREADTABLE_SIZE; i++) {
00306 if (threadtable[i] != NULL) {
00307 debug("gwlib", 0, "Thread %ld (%s) still running",
00308 threadtable[i]->number,
00309 threadtable[i]->name);
00310 running++;
00311 }
00312 }
00313 unlock();
00314
00315 /* We can't do a full cleanup this way */
00316 if (running)
00317 return;
00318
00319 ret = pthread_mutex_destroy(&threadtable_lock);
00320 if (ret != 0) {
00321 warning(ret, "cannot destroy threadtable lock");
00322 }
00323
00324 /* We can't delete the tsd_key here, because gwthread_self()
00325 * still needs it to access the main thread's info. */
00326 }
|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
|
Definition at line 784 of file gwthread-pthread.c. References flushpipe(), getthreadinfo(), threadinfo::wakefd_recv, and warning(). 00785 {
00786 fd_set fd_set_recv;
00787 struct threadinfo *threadinfo;
00788 int fd;
00789 int ret;
00790
00791 threadinfo = getthreadinfo();
00792 fd = threadinfo->wakefd_recv;
00793
00794 FD_ZERO(&fd_set_recv);
00795 FD_SET(fd, &fd_set_recv);
00796
00797 if (dseconds < 0) {
00798 ret = select(fd + 1, &fd_set_recv, NULL, NULL, NULL);
00799 } else {
00800 struct timeval timeout;
00801 timeout.tv_sec = dseconds;
00802 timeout.tv_usec = (dseconds - timeout.tv_sec) * 1000000;
00803
00804 ret = select(fd + 1, &fd_set_recv, NULL, NULL, &timeout);
00805 }
00806
00807 if (ret < 0) {
00808 if (errno != EINTR && errno != EAGAIN) {
00809 warning(errno, "gwthread_sleep_micro: error in select()");
00810 }
00811 }
00812
00813 if (FD_ISSET(fd, &fd_set_recv)) {
00814 flushpipe(fd);
00815 }
00816 }
|
Here is the call graph for this function:

|
|
|
Definition at line 574 of file gwthread-pthread.c. References gwthread_self(), gwthread_wakeup(), and THREAD. Referenced by httpd_restart(), main(), and quit(). 00575 {
00576 long i;
00577 long our_thread = gwthread_self();
00578
00579 for (i = 0; i < THREADTABLE_SIZE; ++i) {
00580 if (THREAD(our_thread) != THREAD(i))
00581 gwthread_wakeup(i);
00582 }
00583 }
|
Here is the call graph for this function:
