Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
gwthread.h File Reference
#include "gw-config.h"

Go to the source code of this file.

Macros

#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)
 

Macro Definition Documentation

#define MAIN_THREAD_ID   0

Typedef Documentation

typedef void gwthread_func_t(void *arg)

Definition at line 79 of file gwthread.h.

Function Documentation

int gwthread_cancel ( long  thread)

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

References debug(), gw_assert(), lock(), threadinfo::name, threadinfo::number, threadinfo::self, THREAD, and unlock().

Referenced by main().

842 {
843  struct threadinfo *threadinfo;
844  int ret;
845 
846  gw_assert(thread >= 0);
847 
848  lock();
849  threadinfo = THREAD(thread);
850  if (threadinfo == NULL || threadinfo->number != thread) {
851  ret = -1;
852  } else {
853  ret = pthread_cancel(threadinfo->self);
854  debug("gwlib.gwthread", 0, "Thread %ld (%s) canceled.",
855  threadinfo->number, threadinfo->name);
856  }
857  unlock();
858  return ret;
859 }
const char * name
gw_assert(wtls_machine->packet_to_send!=NULL)
static void unlock(void)
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#define THREAD(t)
static void lock(void)
pthread_t self
long gwthread_create_real ( gwthread_func_t func,
const char *  funcname,
void *  arg 
)

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

References block_user_signals(), gwthread_self(), MAIN_THREAD_ID, restore_user_signals(), and spawn_thread().

507 {
508  int sigtrick = 0;
509  sigset_t old_signal_set;
510  long thread_id;
511 
512  /*
513  * We want to make sure that only the main thread handles signals,
514  * so that each signal is handled exactly once. To do this, we
515  * make sure that each new thread has all the signals that we
516  * handle blocked. To avoid race conditions, we block them in
517  * the spawning thread first, then create the new thread (which
518  * inherits the settings), and then restore the old settings in
519  * the spawning thread. This means that there is a brief period
520  * when no signals will be processed, but during that time they
521  * should be queued by the operating system.
522  */
523  if (gwthread_self() == MAIN_THREAD_ID)
524  sigtrick = block_user_signals(&old_signal_set) == 0;
525 
526  thread_id = spawn_thread(func, name, arg);
527 
528  /*
529  * Restore the old signal mask. The new thread will have
530  * inherited the resticted one, but the main thread needs
531  * the old one back.
532  */
533  if (sigtrick)
534  restore_user_signals(&old_signal_set);
535 
536  return thread_id;
537 }
long gwthread_self(void)
gwthread_func_t * func
char * name
Definition: smsc_cimd2.c:212
#define MAIN_THREAD_ID
Definition: gwthread.h:77
static long spawn_thread(gwthread_func_t *func, const char *name, void *arg)
static void restore_user_signals(sigset_t *old_set)
static int block_user_signals(sigset_t *old_set_storage)
int gwthread_dumpsigmask ( void  )

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

References debug(), and warning().

876  {
877  sigset_t signal_set;
878  int signum;
879 
880  /* Grab the signal set data from our thread */
881  if (pthread_sigmask(SIG_BLOCK, NULL, &signal_set) != 0) {
882  warning(0, "gwthread_dumpsigmask: Couldn't get signal mask.");
883  return -1;
884  }
885 
886  /* For each signal normally defined (there are usually only 32),
887  * print a message if we don't block it. */
888  for (signum = 1; signum <= 32; signum++) {
889  if (!sigismember(&signal_set, signum)) {
890  debug("gwlib", 0,
891  "gwthread_dumpsigmask: Signal Number %d will be caught.",
892  signum);
893  }
894  }
895  return 0;
896 }
void warning(int err, const char *fmt,...)
Definition: log.c:624
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
void gwthread_init ( void  )

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

References active_threads, fill_threadinfo(), mainthread, panic, threadtable_lock, THREADTABLE_SIZE, and tsd_key.

Referenced by gwlib_init().

268 {
269  int ret;
270  int i;
271 
272  pthread_mutex_init(&threadtable_lock, NULL);
273 
274  ret = pthread_key_create(&tsd_key, NULL);
275  if (ret != 0) {
276  panic(ret, "gwthread-pthread: pthread_key_create failed");
277  }
278 
279  for (i = 0; i < THREADTABLE_SIZE; i++) {
280  threadtable[i] = NULL;
281  }
282  active_threads = 0;
283 
284  /* create main thread info */
285  if (fill_threadinfo(pthread_self(), "main", NULL, &mainthread) == -1)
286  panic(0, "gwthread-pthread: unable to fill main threadinfo.");
287 
288  ret = pthread_setspecific(tsd_key, &mainthread);
289  if (ret != 0)
290  panic(ret, "gwthread-pthread: pthread_setspecific failed");
291 }
#define THREADTABLE_SIZE
static struct threadinfo * threadtable[THREADTABLE_SIZE]
static long active_threads
static long fill_threadinfo(pthread_t id, const char *name, gwthread_func_t *func, struct threadinfo *ti)
static struct threadinfo mainthread
static pthread_mutex_t threadtable_lock
#define panic
Definition: log.h:87
static pthread_key_t tsd_key
void gwthread_join ( long  thread)

Definition at line 539 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(), gw_timerset_destroy(), gwthread_join_all(), heartbeat_stop(), httpd_emu_destroy(), httpsmsc_receiver(), httpsmsc_sender(), io_thread(), 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().

540 {
541  struct threadinfo *threadinfo;
542  pthread_cond_t exit_cond;
543  int ret;
544 
545  gw_assert(thread >= 0);
546 
547  lock();
548  threadinfo = THREAD(thread);
549  if (threadinfo == NULL || threadinfo->number != thread) {
550  /* The other thread has already exited */
551  unlock();
552  return;
553  }
554 
555  /* Register our desire to be alerted when that thread exits,
556  * and wait for it. */
557 
558  ret = pthread_cond_init(&exit_cond, NULL);
559  if (ret != 0) {
560  warning(ret, "gwthread_join: cannot create condition variable.");
561  unlock();
562  return;
563  }
564 
565  if (!threadinfo->joiners)
566  threadinfo->joiners = gwlist_create();
567  gwlist_append(threadinfo->joiners, &exit_cond);
568 
569  /* The wait immediately releases the lock, and reacquires it
570  * when the condition is satisfied. So don't worry, we're not
571  * blocking while keeping the table locked. */
572  pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &threadtable_lock);
573  ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
574  pthread_cleanup_pop(0);
575  unlock();
576 
577  if (ret != 0)
578  warning(ret, "gwthread_join: error in pthread_cond_wait");
579 
580  pthread_cond_destroy(&exit_cond);
581 }
void gwlist_append(List *list, void *item)
Definition: list.c:179
void warning(int err, const char *fmt,...)
Definition: log.c:624
gw_assert(wtls_machine->packet_to_send!=NULL)
static void unlock(void)
static pthread_mutex_t threadtable_lock
#define THREAD(t)
#define gwlist_create()
Definition: list.h:136
static void lock(void)
void gwthread_join_all ( void  )

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

References gwthread_join(), gwthread_self(), THREAD, and THREADTABLE_SIZE.

Referenced by main().

584 {
585  long i;
586  long our_thread = gwthread_self();
587 
588  for (i = 0; i < THREADTABLE_SIZE; ++i) {
589  if (THREAD(our_thread) != THREAD(i))
590  gwthread_join(i);
591  }
592 }
#define THREADTABLE_SIZE
long gwthread_self(void)
void gwthread_join(long thread)
#define THREAD(t)
void gwthread_join_every ( gwthread_func_t func)

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

References debug(), threadinfo::func, gwlist_append(), gwlist_create, threadinfo::joiners, lock(), threadinfo::name, threadinfo::number, THREAD, threadtable_lock, THREADTABLE_SIZE, 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().

606 {
607  struct threadinfo *ti;
608  pthread_cond_t exit_cond;
609  int ret;
610  long i;
611 
612  ret = pthread_cond_init(&exit_cond, NULL);
613  if (ret != 0) {
614  warning(ret, "gwthread_join_every: cannot create condition variable.");
615  unlock();
616  return;
617  }
618 
619  /*
620  * FIXME: To be really safe, this function should keep looping
621  * over the table until it does a complete run without having
622  * to call pthread_cond_wait. Otherwise, new threads could
623  * start while we wait, and we'll miss them.
624  */
625  lock();
626  for (i = 0; i < THREADTABLE_SIZE; ++i) {
627  ti = THREAD(i);
628  if (ti == NULL || ti->func != func)
629  continue;
630  debug("gwlib.gwthread", 0,
631  "Waiting for %ld (%s) to terminate",
632  ti->number, ti->name);
633  if (!ti->joiners)
634  ti->joiners = gwlist_create();
635  gwlist_append(ti->joiners, &exit_cond);
636  pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &threadtable_lock);
637  ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
638  pthread_cleanup_pop(0);
639  if (ret != 0)
640  warning(ret, "gwthread_join_all: error in pthread_cond_wait");
641  }
642  unlock();
643 
644  pthread_cond_destroy(&exit_cond);
645 }
#define THREADTABLE_SIZE
void gwlist_append(List *list, void *item)
Definition: list.c:179
const char * name
gwthread_func_t * func
void warning(int err, const char *fmt,...)
Definition: log.c:624
static void unlock(void)
static pthread_mutex_t threadtable_lock
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#define THREAD(t)
#define gwlist_create()
Definition: list.h:136
static void lock(void)
int gwthread_poll ( struct pollfd fds,
long  numfds,
double  timeout 
)

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

References error(), pollfd::events, pollfd::fd, flushpipe(), getthreadinfo(), poll, POLL_NOTIMEOUT, POLLIN, pollfd::revents, and threadinfo::wakefd_recv.

Referenced by poller(), and server_thread().

739 {
740  struct pollfd *pollfds;
741  struct threadinfo *threadinfo;
742  int milliseconds;
743  int ret;
744 
745  threadinfo = getthreadinfo();
746 
747  /* Create a new pollfd array with an extra element for the
748  * thread wakeup fd. */
749 
750  pollfds = gw_malloc((numfds + 1) * sizeof(*pollfds));
751  pollfds[0].fd = threadinfo->wakefd_recv;
752  pollfds[0].events = POLLIN;
753  pollfds[0].revents = 0;
754  memcpy(pollfds + 1, fds, numfds * sizeof(*pollfds));
755 
756  milliseconds = timeout * 1000;
757  if (milliseconds < 0)
758  milliseconds = POLL_NOTIMEOUT;
759 
760  ret = poll(pollfds, numfds + 1, milliseconds);
761  if (ret < 0) {
762  if (errno != EINTR)
763  error(errno, "gwthread_poll: error in poll");
764  gw_free(pollfds);
765  return -1;
766  }
767  if (pollfds[0].revents)
768  flushpipe(pollfds[0].fd);
769 
770  /* Copy the results back to the caller */
771  memcpy(fds, pollfds + 1, numfds * sizeof(*pollfds));
772  gw_free(pollfds);
773 
774  return ret;
775 }
void error(int err, const char *fmt,...)
Definition: log.c:612
#define poll(fdarray, numfds, timeout)
Definition: gwpoll.h:104
#define POLL_NOTIMEOUT
Definition: gwpoll.h:100
short events
Definition: gwpoll.h:86
#define POLLIN
Definition: gwpoll.h:91
static struct threadinfo * getthreadinfo(void)
Definition: gwpoll.h:84
int fd
Definition: gwpoll.h:85
short revents
Definition: gwpoll.h:87
static void flushpipe(int fd)
int gwthread_pollfd ( int  fd,
int  events,
double  timeout 
)

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

References error(), pollfd::events, pollfd::fd, flushpipe(), getthreadinfo(), poll, POLL_NOTIMEOUT, POLLIN, 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().

705 {
706  struct pollfd pollfd[2];
707  struct threadinfo *threadinfo;
708  int milliseconds;
709  int ret;
710 
711  threadinfo = getthreadinfo();
712 
713  pollfd[0].fd = threadinfo->wakefd_recv;
714  pollfd[0].events = POLLIN;
715  pollfd[0].revents = 0;
716 
717  pollfd[1].fd = fd;
718  pollfd[1].events = events;
719  pollfd[1].revents = 0;
720 
721  milliseconds = timeout * 1000;
722  if (milliseconds < 0)
723  milliseconds = POLL_NOTIMEOUT;
724 
725  ret = poll(pollfd, 2, milliseconds);
726  if (ret < 0) {
727  if (errno != EINTR)
728  error(errno, "gwthread_pollfd: error in poll");
729  return -1;
730  }
731 
732  if (pollfd[0].revents)
733  flushpipe(pollfd[0].fd);
734 
735  return pollfd[1].revents;
736 }
void error(int err, const char *fmt,...)
Definition: log.c:612
#define poll(fdarray, numfds, timeout)
Definition: gwpoll.h:104
#define POLL_NOTIMEOUT
Definition: gwpoll.h:100
short events
Definition: gwpoll.h:86
#define POLLIN
Definition: gwpoll.h:91
static struct threadinfo * getthreadinfo(void)
Definition: gwpoll.h:84
int fd
Definition: gwpoll.h:85
short revents
Definition: gwpoll.h:87
static void flushpipe(int fd)
long gwthread_self ( void  )

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

649 {
650  struct threadinfo *threadinfo;
651  threadinfo = pthread_getspecific(tsd_key);
652  if (threadinfo)
653  return threadinfo->number;
654  else
655  return -1;
656 }
static pthread_key_t tsd_key
void gwthread_self_ids ( long *  tid,
long *  pid 
)

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

References threadinfo::number, threadinfo::pid, and tsd_key.

Referenced by format().

670 {
671  struct threadinfo *threadinfo;
672  threadinfo = pthread_getspecific(tsd_key);
673  if (threadinfo) {
674  *tid = threadinfo->number;
675  *pid = (threadinfo->pid != -1) ? threadinfo->pid : getpid();
676  } else {
677  *tid = -1;
678  *pid = getpid();
679  }
680 }
static pthread_key_t tsd_key
long gwthread_self_pid ( void  )

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

References threadinfo::pid, and tsd_key.

660 {
661  struct threadinfo *threadinfo;
662  threadinfo = pthread_getspecific(tsd_key);
663  if (threadinfo && threadinfo->pid != -1)
664  return (long) threadinfo->pid;
665  else
666  return (long) getpid();
667 }
static pthread_key_t tsd_key
int gwthread_shouldhandlesignal ( int  signal)

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

Referenced by signal_handler().

865  {
866  return 1;
867 }
void gwthread_shutdown ( void  )

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

References debug(), gw_assert(), lock(), name, number, running, threadtable_lock, THREADTABLE_SIZE, unlock(), and warning().

Referenced by gwlib_shutdown().

297 {
298  int ret;
299  int running;
300  int i;
301 
302  /* Main thread must not have disappeared */
303  gw_assert(threadtable[0] != NULL);
304  lock();
305 
306  running = 0;
307  /* Start i at 1 to skip the main thread, which is supposed to be
308  * still running. */
309  for (i = 1; i < THREADTABLE_SIZE; i++) {
310  if (threadtable[i] != NULL) {
311  debug("gwlib", 0, "Thread %ld (%s) still running",
312  threadtable[i]->number,
313  threadtable[i]->name);
314  running++;
315  }
316  }
317  unlock();
318 
319  /* We can't do a full cleanup this way */
320  if (running)
321  return;
322 
323  ret = pthread_mutex_destroy(&threadtable_lock);
324  if (ret != 0) {
325  warning(ret, "cannot destroy threadtable lock");
326  }
327 
328  /* We can't delete the tsd_key here, because gwthread_self()
329  * still needs it to access the main thread's info. */
330 }
#define THREADTABLE_SIZE
int number
Definition: smsc_cimd2.c:213
static struct threadinfo * threadtable[THREADTABLE_SIZE]
Definition: shared.h:81
char * name
Definition: smsc_cimd2.c:212
void warning(int err, const char *fmt,...)
Definition: log.c:624
gw_assert(wtls_machine->packet_to_send!=NULL)
static void unlock(void)
static pthread_mutex_t threadtable_lock
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
static void lock(void)
void gwthread_sleep ( double  seconds)

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

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

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

779 {
780  struct pollfd pollfd;
781  struct threadinfo *threadinfo;
782  int milliseconds;
783  int ret;
784 
785  threadinfo = getthreadinfo();
786 
787  pollfd.fd = threadinfo->wakefd_recv;
788  pollfd.events = POLLIN;
789 
790  milliseconds = seconds * 1000;
791  if (milliseconds < 0)
792  milliseconds = POLL_NOTIMEOUT;
793 
794  ret = poll(&pollfd, 1, milliseconds);
795  if (ret < 0) {
796  if (errno != EINTR && errno != EAGAIN) {
797  warning(errno, "gwthread_sleep: error in poll");
798  }
799  }
800  if (ret == 1) {
802  }
803 }
#define poll(fdarray, numfds, timeout)
Definition: gwpoll.h:104
#define POLL_NOTIMEOUT
Definition: gwpoll.h:100
short events
Definition: gwpoll.h:86
#define POLLIN
Definition: gwpoll.h:91
static struct threadinfo * getthreadinfo(void)
void warning(int err, const char *fmt,...)
Definition: log.c:624
Definition: gwpoll.h:84
int fd
Definition: gwpoll.h:85
static void flushpipe(int fd)
void gwthread_sleep_micro ( double  dseconds)

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

References flushpipe(), getthreadinfo(), threadinfo::wakefd_recv, and warning().

807 {
808  fd_set fd_set_recv;
809  struct threadinfo *threadinfo;
810  int fd;
811  int ret;
812 
813  threadinfo = getthreadinfo();
814  fd = threadinfo->wakefd_recv;
815 
816  FD_ZERO(&fd_set_recv);
817  FD_SET(fd, &fd_set_recv);
818 
819  if (dseconds < 0) {
820  ret = select(fd + 1, &fd_set_recv, NULL, NULL, NULL);
821  } else {
822  struct timeval timeout;
823  timeout.tv_sec = dseconds;
824  timeout.tv_usec = (dseconds - timeout.tv_sec) * 1000000;
825 
826  ret = select(fd + 1, &fd_set_recv, NULL, NULL, &timeout);
827  }
828 
829  if (ret < 0) {
830  if (errno != EINTR && errno != EAGAIN) {
831  warning(errno, "gwthread_sleep_micro: error in select()");
832  }
833  }
834 
835  if (FD_ISSET(fd, &fd_set_recv)) {
836  flushpipe(fd);
837  }
838 }
static struct threadinfo * getthreadinfo(void)
void warning(int err, const char *fmt,...)
Definition: log.c:624
static void flushpipe(int fd)
void gwthread_wakeup ( long  thread)

Definition at line 682 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(), client_destroy(), emi2_idleprocessing(), emi2_listener(), emi2_sender(), gw_timer_elapsed_start(), gw_timer_start(), gw_timerset_destroy(), gwthread_wakeup_all(), gwtimer_start(), heartbeat_stop(), http_close_all_ports(), http_close_port(), http_open_port_if(), httpd_shutdown(), httpsmsc_receiver(), httpsmsc_sender(), httpsmsc_shutdown(), io_thread(), 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_graceful_restart(), 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().

683 {
684  unsigned char c = 0;
685  struct threadinfo *threadinfo;
686  int fd;
687 
688  gw_assert(thread >= 0);
689 
690  lock();
691 
692  threadinfo = THREAD(thread);
693  if (threadinfo == NULL || threadinfo->number != thread) {
694  unlock();
695  return;
696  }
697 
698  fd = threadinfo->wakefd_send;
699  unlock();
700 
701  write(fd, &c, 1);
702 }
gw_assert(wtls_machine->packet_to_send!=NULL)
static void unlock(void)
#define THREAD(t)
static void lock(void)
void gwthread_wakeup_all ( void  )

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

References gwthread_self(), gwthread_wakeup(), THREAD, and THREADTABLE_SIZE.

Referenced by httpd_restart(), main(), and quit().

595 {
596  long i;
597  long our_thread = gwthread_self();
598 
599  for (i = 0; i < THREADTABLE_SIZE; ++i) {
600  if (THREAD(our_thread) != THREAD(i))
601  gwthread_wakeup(i);
602  }
603 }
#define THREADTABLE_SIZE
long gwthread_self(void)
#define THREAD(t)
void gwthread_wakeup(long thread)
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.