Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

gwthread.h File Reference

#include "gw-config.h"
#include <sys/poll.h>

Include dependency graph for gwthread.h:

Include dependency graph

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

Included by dependency graph

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)


Define Documentation

#define gwthread_create func,
arg   )     (gwthread_create_real(func, __FILE__ ":" #func, arg))
 

Definition at line 88 of file gwthread.h.

Referenced by accept_thread(), add_service(), fdset_create_real(), heartbeat_start(), httpadmin_start(), httpd_emu_create(), init_smsbox(), main(), main_for_producer_and_consumer(), radius_acct_init(), receive_smpp_thread(), run_smsbox(), run_wapbox(), smpp_emu(), smpp_emu_handle_pdu(), smsbox_start(), smsc2_start(), smsc_at2_create(), smsc_cgw_create(), smsc_cimd2_create(), smsc_emi2_create(), smsc_emu_create(), smsc_fake_create(), smsc_http_create(), smsc_oisd_create(), smsc_smasi_create(), smsc_smpp_create(), smsc_soap_create(), smsc_wrapper_create(), soap_server_start(), soap_start_cb(), start_client_threads(), start_http_thread(), start_server_thread(), start_wap(), store_file_load(), timers_init(), wait_for_connections(), wap_appl_init(), wap_push_ota_init(), wap_push_ppg_init(), wapbox_start(), wsp_push_client_init(), wsp_session_init(), wsp_unit_init(), wtp_initiator_init(), and wtp_resp_init().

#define MAIN_THREAD_ID   0
 

Definition at line 75 of file gwthread.h.

Referenced by httpd_shutdown(), sms_router(), smsboxc_run(), udp_receiver(), and wapboxc_run().


Typedef Documentation

typedef void gwthread_func_t(void *arg)
 

Definition at line 77 of file gwthread.h.


Function Documentation

int gwthread_cancel long  thread  ) 
 

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 }

long gwthread_create_real gwthread_func_t func,
const char *  funcname,
void *  arg
 

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:

int gwthread_dumpsigmask void   ) 
 

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:

void gwthread_init void   ) 
 

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:

void gwthread_join long  thread  ) 
 

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:

void gwthread_join_all void   ) 
 

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:

void gwthread_join_every gwthread_func_t func  ) 
 

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:

int gwthread_poll struct pollfd fds,
long  numfds,
double  timeout
 

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:

int gwthread_pollfd int  fd,
int  events,
double  timeout
 

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:

long gwthread_self void   ) 
 

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 }

void gwthread_self_ids long *  tid,
long *  pid
 

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 }

long gwthread_self_pid void   ) 
 

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 }

int gwthread_shouldhandlesignal int  signal  ) 
 

Definition at line 837 of file gwthread-pthread.c.

Referenced by signal_handler().

00837                                            {
00838     return 1;
00839 }

void gwthread_shutdown void   ) 
 

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:

void gwthread_sleep double  seconds  ) 
 

Definition at line 756 of file gwthread-pthread.c.

References pollfd::events, pollfd::fd, flushpipe(), getthreadinfo(), poll, threadinfo::wakefd_recv, and warning().

Referenced by at2_device_thread(), at2_init_device(), at2_login_device(), at2_send_one_message(), at2_write(), at2_write_ctrlz(), at2_write_line(), bb_smscconn_receive(), cgw_open_send_connection(), client_thread(), dbpool_conn_consume(), emi2_do_send(), emi2_wait(), heartbeat_thread(), http_queue_thread(), httpd_check_authorization(), httpsmsc_send(), httpsmsc_send_cb(), io_thread(), main(), main_connection_loop(), open_send_connection(), parachute_start(), poller(), port_remove(), push_thread(), reconnect(), send_message(), send_messages(), send_smpp_thread(), smasi_thread(), sms_router(), sms_to_smsboxes(), smsbox_thread(), smsboxc_run(), soap_listener(), soap_server(), store_dumper(), thread1(), thread2(), wait_for_connections(), wapboxc_run(), watch_timers(), and wrapper_receiver().

00757 {
00758     struct pollfd pollfd;
00759     struct threadinfo *threadinfo;
00760     int milliseconds;
00761     int ret;
00762 
00763     threadinfo = getthreadinfo();
00764 
00765     pollfd.fd = threadinfo->wakefd_recv;
00766     pollfd.events = POLLIN;
00767 
00768     milliseconds = seconds * 1000;
00769     if (milliseconds < 0)
00770         milliseconds = POLL_NOTIMEOUT;
00771 
00772     ret = poll(&pollfd, 1, milliseconds);
00773     if (ret < 0) {
00774         if (errno != EINTR && errno != EAGAIN) {
00775             warning(errno, "gwthread_sleep: error in poll");
00776         }
00777     }
00778     if (ret == 1) {
00779         flushpipe(pollfd.fd);
00780     }
00781 }

Here is the call graph for this function:

void gwthread_sleep_micro double  dseconds  ) 
 

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:

void gwthread_wakeup long  thread  ) 
 

Definition at line 660 of file gwthread-pthread.c.

References gw_assert, lock, threadinfo::number, THREAD, unlock, and threadinfo::wakefd_send.

Referenced by add_msg_cb(), at2_add_msg_cb(), at2_shutdown_cb(), at2_start_cb(), bb_smscconn_connected(), boxc_receiver(), cgw_add_msg_cb(), cgw_listener(), cgw_shutdown_cb(), cgw_start_cb(), cimd2_add_msg_cb(), cimd2_shutdown_cb(), cimd2_start_cb(), emi2_idleprocessing(), emi2_listener(), emi2_sender(), gwthread_wakeup_all(), gwtimer_start(), heartbeat_stop(), http_close_all_ports(), http_close_port(), http_open_port_if(), httpd_shutdown(), main(), oisd_add_msg_cb(), oisd_shutdown_cb(), oisd_start_cb(), run_smsbox(), send_msg_cb(), server_shutdown(), shutdown_cb(), smpp_emu(), sms_router(), smsboxc_run(), smsc2_restart_smsc(), smsc2_resume(), smsc2_shutdown(), smsc_cimd2_create(), smsc_emi2_create(), smsc_emu_destroy(), smsc_oisd_create(), smsc_smpp_create(), soap_add_msg_cb(), soap_server_stop(), soap_shutdown_cb(), start_cb(), store_file_shutdown(), submit_action(), submit_action_nosync(), timers_shutdown(), udp_receiver(), wapboxc_run(), wrapper_sender(), and wrapper_shutdown().

00661 {
00662     unsigned char c = 0;
00663     struct threadinfo *threadinfo;
00664     int fd;
00665 
00666     gw_assert(thread >= 0);
00667 
00668     lock();
00669 
00670     threadinfo = THREAD(thread);
00671     if (threadinfo == NULL || threadinfo->number != thread) {
00672         unlock();
00673         return;
00674     }
00675 
00676     fd = threadinfo->wakefd_send;
00677     unlock();
00678 
00679     write(fd, &c, 1);
00680 }

void gwthread_wakeup_all void   ) 
 

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:

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.