#include <unistd.h>#include <errno.h>#include <pthread.h>#include <signal.h>#include <string.h>#include "gwlib/gwlib.h"#include <openssl/err.h>Include dependency graph for gwthread-pthread.c:

Go to the source code of this file.
Data Structures | |
| struct | threadinfo |
| struct | new_thread_args |
Defines | |
| #define | THREADTABLE_SIZE 1024 |
| #define | THREAD(t) (threadtable[(t) % THREADTABLE_SIZE]) |
Functions | |
| void | lock (void) |
| void | unlock (void) |
| void | flushpipe (int fd) |
| long | fill_threadinfo (pthread_t id, const char *name, gwthread_func_t *func, struct threadinfo *ti) |
| threadinfo * | getthreadinfo (void) |
| void | alert_joiners (void) |
| void | delete_threadinfo (void) |
| void | gwthread_init (void) |
| void | gwthread_shutdown (void) |
| void * | new_thread (void *arg) |
| int | block_user_signals (sigset_t *old_set_storage) |
| void | restore_user_signals (sigset_t *old_set) |
| long | spawn_thread (gwthread_func_t *func, const char *name, void *arg) |
| long | gwthread_create_real (gwthread_func_t *func, const char *name, void *arg) |
| void | gwthread_join (long thread) |
| void | gwthread_join_all (void) |
| void | gwthread_wakeup_all (void) |
| void | gwthread_join_every (gwthread_func_t *func) |
| long | gwthread_self (void) |
| long | gwthread_self_pid (void) |
| void | gwthread_self_ids (long *tid, long *pid) |
| void | gwthread_wakeup (long thread) |
| 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) |
Variables | |
| threadinfo * | threadtable [THREADTABLE_SIZE] |
| long | active_threads = 0 |
| long | next_threadnumber |
| threadinfo | mainthread |
| pthread_key_t | tsd_key |
| pthread_mutex_t | threadtable_lock |
|
|
Definition at line 107 of file gwthread-pthread.c. Referenced by delete_threadinfo(), fill_threadinfo(), gwthread_cancel(), gwthread_join(), gwthread_join_all(), gwthread_join_every(), gwthread_wakeup(), and gwthread_wakeup_all(). |
|
|
Definition at line 78 of file gwthread-pthread.c. Referenced by fill_threadinfo(). |
|
|
Definition at line 232 of file gwthread-pthread.c. References getthreadinfo(), gwlist_extract_first(), and threadinfo::joiners. Referenced by new_thread(). 00233 {
00234 struct threadinfo *threadinfo;
00235 pthread_cond_t *joiner_cond;
00236
00237 threadinfo = getthreadinfo();
00238 if (!threadinfo->joiners)
00239 return;
00240 while ((joiner_cond = gwlist_extract_first(threadinfo->joiners))) {
00241 pthread_cond_broadcast(joiner_cond);
00242 }
00243 }
|
Here is the call graph for this function:

|
|
Definition at line 397 of file gwthread-pthread.c. References error(). Referenced by gwthread_create_real(). 00398 {
00399 int ret;
00400 sigset_t block_signals;
00401
00402 ret = sigemptyset(&block_signals);
00403 if (ret != 0) {
00404 error(errno, "gwthread-pthread: Couldn't initialize signal set");
00405 return -1;
00406 }
00407 ret = sigaddset(&block_signals, SIGHUP);
00408 ret |= sigaddset(&block_signals, SIGTERM);
00409 ret |= sigaddset(&block_signals, SIGQUIT);
00410 ret |= sigaddset(&block_signals, SIGINT);
00411 if (ret != 0) {
00412 error(0, "gwthread-pthread: Couldn't add signal to signal set");
00413 return -1;
00414 }
00415 ret = pthread_sigmask(SIG_BLOCK, &block_signals, old_set_storage);
00416 if (ret != 0) {
00417 error(ret,
00418 "gwthread-pthread: Couldn't disable signals for thread creation");
00419 return -1;
00420 }
00421 return 0;
00422 }
|
Here is the call graph for this function:

|
|
Definition at line 245 of file gwthread-pthread.c. References active_threads, getthreadinfo(), gw_assert, gwlist_destroy(), threadinfo::joiners, mainthread, threadinfo::number, THREAD, threadinfo::wakefd_recv, and threadinfo::wakefd_send. Referenced by new_thread(). 00246 {
00247 struct threadinfo *threadinfo;
00248
00249 threadinfo = getthreadinfo();
00250 gwlist_destroy(threadinfo->joiners, NULL);
00251 if (threadinfo->wakefd_recv != -1)
00252 close(threadinfo->wakefd_recv);
00253 if (threadinfo->wakefd_send != -1)
00254 close(threadinfo->wakefd_send);
00255 if (threadinfo->number != -1) {
00256 THREAD(threadinfo->number) = NULL;
00257 active_threads--;
00258 }
00259 gw_assert(threadinfo != &mainthread);
00260 gw_free(threadinfo);
00261 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 167 of file gwthread-pthread.c. References active_threads, error(), threadinfo::func, gw_assert, threadinfo::joiners, threadinfo::name, next_threadnumber, threadinfo::number, threadinfo::pid, threadinfo::self, socket_set_blocking(), THREAD, THREADTABLE_SIZE, threadinfo::wakefd_recv, and threadinfo::wakefd_send. Referenced by gwthread_init(), and spawn_thread(). 00170 {
00171 int pipefds[2];
00172 long first_try;
00173
00174 gw_assert(active_threads < THREADTABLE_SIZE);
00175
00176 /* initialize to default values */
00177 ti->self = id;
00178 ti->name = name;
00179 ti->func = func;
00180 ti->pid = -1;
00181 ti->wakefd_recv = -1;
00182 ti->wakefd_send = -1;
00183 ti->joiners = NULL;
00184 ti->number = -1;
00185
00186 if (pipe(pipefds) < 0) {
00187 error(errno, "cannot allocate wakeup pipe for new thread");
00188 return -1;
00189 }
00190 ti->wakefd_recv = pipefds[0];
00191 ti->wakefd_send = pipefds[1];
00192 socket_set_blocking(ti->wakefd_recv, 0);
00193 socket_set_blocking(ti->wakefd_send, 0);
00194
00195 /* Find a free table entry and claim it. */
00196 first_try = next_threadnumber;
00197 do {
00198 ti->number = next_threadnumber++;
00199 /* Check if we looped all the way around the thread table. */
00200 if (ti->number == first_try + THREADTABLE_SIZE) {
00201 error(0, "Cannot have more than %d active threads", THREADTABLE_SIZE);
00202 ti->number = -1;
00203 return -1;
00204 }
00205 } while (THREAD(ti->number) != NULL);
00206 THREAD(ti->number) = ti;
00207
00208 active_threads++;
00209
00210 return ti->number;
00211 }
|
Here is the call graph for this function:

|
|
Definition at line 153 of file gwthread-pthread.c. Referenced by gwthread_poll(), gwthread_pollfd(), gwthread_sleep(), and gwthread_sleep_micro(). 00154 {
00155 unsigned char buf[128];
00156 ssize_t bytes;
00157
00158 do {
00159 bytes = read(fd, buf, sizeof(buf));
00160 } while (bytes > 0);
00161 }
|
|
|
Definition at line 214 of file gwthread-pthread.c. References gw_assert, panic, threadinfo::self, and tsd_key. Referenced by alert_joiners(), delete_threadinfo(), gwthread_poll(), gwthread_pollfd(), gwthread_sleep(), and gwthread_sleep_micro(). 00215 {
00216 struct threadinfo *threadinfo;
00217
00218 threadinfo = pthread_getspecific(tsd_key);
00219 if (threadinfo == NULL) {
00220 panic(0, "gwthread-pthread: pthread_getspecific failed");
00221 } else {
00222 gw_assert(pthread_equal(threadinfo->self, pthread_self()));
00223 }
00224 return threadinfo;
00225 }
|
|
|
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. References threadinfo::number, and tsd_key. Referenced by client_thread(), conn_claim(), fdset_destroy(), fdset_listen(), fdset_register(), fdset_set_timeout(), fdset_unregister(), find_entry(), gw_prioqueue_consume(), gw_rwlock_unlock(), gw_rwlock_wrlock(), gwlist_consume(), gwlist_timed_consume(), gwlist_wait_until_nonempty(), gwthread_create_real(), gwthread_join_all(), gwthread_wakeup_all(), handle_action(), lock_in(), lock_out(), mutex_lock_real(), mutex_trylock_real(), new_thread(), openssl_init_locks(), producer(), and push_thread(). 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:

|
|
Definition at line 131 of file gwthread-pthread.c. References panic, and threadtable_lock. 00132 {
00133 int ret;
00134
00135 ret = pthread_mutex_lock(&threadtable_lock);
00136 if (ret != 0) {
00137 panic(ret, "gwthread-pthread: could not lock thread table");
00138 }
00139 }
|
|
|
Definition at line 328 of file gwthread-pthread.c. References alert_joiners(), new_thread_args::arg, debug(), delete_threadinfo(), new_thread_args::failed, new_thread_args::func, gwthread_self(), lock, threadinfo::name, threadinfo::number, panic, threadinfo::pid, new_thread_args::ti, tsd_key, and unlock. Referenced by spawn_thread(). 00329 {
00330 int ret;
00331 struct new_thread_args *p = arg;
00332
00333 /* Make sure we don't start until our parent has entered
00334 * our thread info in the thread table. */
00335 lock();
00336 /* check for initialization errors */
00337 if (p->failed) {
00338 /* Must free p before signaling our exit, otherwise there is
00339 * a race with gw_check_leaks at shutdown. */
00340 gw_free(p);
00341 delete_threadinfo();
00342 unlock();
00343 return NULL;
00344 }
00345 unlock();
00346
00347 /* This has to be done here, because pthread_setspecific cannot
00348 * be called by our parent on our behalf. That's why the ti
00349 * pointer is passed in the new_thread_args structure. */
00350 /* Synchronization is not a problem, because the only thread
00351 * that relies on this call having been made is this one --
00352 * no other thread can access our TSD anyway. */
00353 ret = pthread_setspecific(tsd_key, p->ti);
00354 if (ret != 0) {
00355 panic(ret, "gwthread-pthread: pthread_setspecific failed");
00356 }
00357
00358 p->ti->pid = getpid();
00359 debug("gwlib.gwthread", 0, "Thread %ld (%s) maps to pid %ld.",
00360 p->ti->number, p->ti->name, (long) p->ti->pid);
00361
00362 (p->func)(p->arg);
00363
00364 lock();
00365 debug("gwlib.gwthread", 0, "Thread %ld (%s) terminates.",
00366 p->ti->number, p->ti->name);
00367 alert_joiners();
00368 #ifdef HAVE_LIBSSL
00369 /* Clear the OpenSSL thread-specific error queue to avoid
00370 * memory leaks. */
00371 ERR_remove_state(gwthread_self());
00372 #endif /* HAVE_LIBSSL */
00373 /* Must free p before signaling our exit, otherwise there is
00374 * a race with gw_check_leaks at shutdown. */
00375 gw_free(p);
00376 delete_threadinfo();
00377 unlock();
00378
00379 return NULL;
00380 }
|
Here is the call graph for this function:

|
|
Definition at line 424 of file gwthread-pthread.c. References panic. Referenced by gwthread_create_real(). 00425 {
00426 int ret;
00427
00428 ret = pthread_sigmask(SIG_SETMASK, old_set, NULL);
00429 if (ret != 0) {
00430 panic(ret, "gwthread-pthread: Couldn't restore signal set.");
00431 }
00432 }
|
|
||||||||||||||||
|
Definition at line 435 of file gwthread-pthread.c. References active_threads, new_thread_args::arg, debug(), error(), fill_threadinfo(), new_thread_args::func, lock, name, new_thread(), new_thread_args::ti, unlock, and warning(). Referenced by gwthread_create_real(). 00436 {
00437 int ret;
00438 pthread_t id;
00439 struct new_thread_args *p = NULL;
00440 long new_thread_id;
00441
00442 /* We want to pass both these arguments to our wrapper function
00443 * new_thread, but the pthread_create interface will only let
00444 * us pass one pointer. So we wrap them in a little struct. */
00445 p = gw_malloc(sizeof(*p));
00446 p->func = func;
00447 p->arg = arg;
00448 p->ti = gw_malloc(sizeof(*(p->ti)));
00449 p->failed = 0;
00450
00451 /* Lock the thread table here, so that new_thread can block
00452 * on that lock. That way, the new thread won't start until
00453 * we have entered it in the thread table. */
00454 lock();
00455
00456 if (active_threads >= THREADTABLE_SIZE) {
00457 unlock();
00458 warning(0, "Too many threads, could not create new thread.");
00459 gw_free(p);
00460 return -1;
00461 }
00462
00463 ret = pthread_create(&id, NULL, &new_thread, p);
00464 if (ret != 0) {
00465 unlock();
00466 error(ret, "Could not create new thread.");
00467 gw_free(p);
00468 return -1;
00469 }
00470 ret = pthread_detach(id);
00471 if (ret != 0) {
00472 error(ret, "Could not detach new thread.");
00473 }
00474
00475 new_thread_id = fill_threadinfo(id, name, func, p->ti);
00476 if (new_thread_id == -1)
00477 p->failed = 1;
00478 unlock();
00479
00480 if (new_thread_id != -1)
00481 debug("gwlib.gwthread", 0, "Started thread %ld (%s)", new_thread_id, name);
00482 else
00483 debug("gwlib.gwthread", 0, "Failed to start thread (%s)", name);
00484
00485 return new_thread_id;
00486 }
|
Here is the call graph for this function:

|
|
Definition at line 141 of file gwthread-pthread.c. References panic, and threadtable_lock. 00142 {
00143 int ret;
00144
00145 ret = pthread_mutex_unlock(&threadtable_lock);
00146 if (ret != 0) {
00147 panic(ret, "gwthread-pthread: could not unlock thread table");
00148 }
00149 }
|
|
|
Definition at line 110 of file gwthread-pthread.c. Referenced by delete_threadinfo(), fill_threadinfo(), gwthread_init(), and spawn_thread(). |
|
|
Definition at line 122 of file gwthread-pthread.c. Referenced by delete_threadinfo(), and gwthread_init(). |
|
|
Definition at line 116 of file gwthread-pthread.c. Referenced by fill_threadinfo(). |
|
|
Definition at line 106 of file gwthread-pthread.c. Referenced by gwthread_init(), and gwthread_shutdown(). |
|
|
Definition at line 129 of file gwthread-pthread.c. Referenced by gwthread_init(), gwthread_join(), gwthread_join_every(), gwthread_shutdown(), lock(), and unlock(). |
|
|
Definition at line 127 of file gwthread-pthread.c. Referenced by getthreadinfo(), gwthread_init(), gwthread_self(), gwthread_self_ids(), gwthread_self_pid(), and new_thread(). |