72 #include <openssl/err.h> 78 #define THREADTABLE_SIZE 4096 107 #define THREAD(t) (threadtable[(t) % THREADTABLE_SIZE]) 137 panic(ret,
"gwthread-pthread: could not lock thread table");
147 panic(ret,
"gwthread-pthread: could not unlock thread table");
155 unsigned char buf[128];
159 bytes = read(fd, buf,
sizeof(buf));
186 if (pipe(pipefds) < 0) {
187 error(errno,
"cannot allocate wakeup pipe for new thread");
224 panic(0,
"gwthread-pthread: pthread_getspecific failed");
239 pthread_cond_t *joiner_cond;
245 pthread_cond_broadcast(joiner_cond);
274 ret = pthread_key_create(&
tsd_key, NULL);
276 panic(ret,
"gwthread-pthread: pthread_key_create failed");
286 panic(0,
"gwthread-pthread: unable to fill main threadinfo.");
290 panic(ret,
"gwthread-pthread: pthread_setspecific failed");
311 debug(
"gwlib", 0,
"Thread %ld (%s) still running",
325 warning(ret,
"cannot destroy threadtable lock");
337 debug(
"gwlib.gwthread", 0,
"Thread %ld (%s) terminates.",
341 #if OPENSSL_VERSION_NUMBER < 0x10100000L 379 ret = pthread_setspecific(
tsd_key, p->
ti);
381 panic(ret,
"gwthread-pthread: pthread_setspecific failed");
384 p->
ti->
pid = getpid();
385 debug(
"gwlib.gwthread", 0,
"Thread %ld (%s) maps to pid %ld.",
393 pthread_cleanup_pop(0);
411 #if defined(DARWIN_OLD) 412 static int pthread_sigmask();
418 sigset_t block_signals;
420 ret = sigemptyset(&block_signals);
422 error(errno,
"gwthread-pthread: Couldn't initialize signal set");
425 ret = sigaddset(&block_signals, SIGHUP);
426 ret |= sigaddset(&block_signals, SIGTERM);
427 ret |= sigaddset(&block_signals, SIGQUIT);
428 ret |= sigaddset(&block_signals, SIGINT);
430 error(0,
"gwthread-pthread: Couldn't add signal to signal set");
433 ret = pthread_sigmask(SIG_BLOCK, &block_signals, old_set_storage);
436 "gwthread-pthread: Couldn't disable signals for thread creation");
446 ret = pthread_sigmask(SIG_SETMASK, old_set, NULL);
448 panic(ret,
"gwthread-pthread: Couldn't restore signal set.");
463 p = gw_malloc(
sizeof(*p));
466 p->
ti = gw_malloc(
sizeof(*(p->
ti)));
476 error(0,
"Too many threads, could not create new thread.");
482 ret = pthread_create(&
id, NULL, &
new_thread, p);
485 error(ret,
"Could not create new thread.");
490 ret = pthread_detach(
id);
492 error(ret,
"Could not detach new thread.");
496 if (new_thread_id == -1)
500 if (new_thread_id != -1)
501 debug(
"gwlib.gwthread", 0,
"Started thread %ld (%s)", new_thread_id,
name);
503 debug(
"gwlib.gwthread", 0,
"Failed to start thread (%s)",
name);
505 return new_thread_id;
511 sigset_t old_signal_set;
544 pthread_cond_t exit_cond;
560 ret = pthread_cond_init(&exit_cond, NULL);
562 warning(ret,
"gwthread_join: cannot create condition variable.");
574 pthread_cleanup_push((
void(*)(
void*))pthread_mutex_unlock, &
threadtable_lock);
576 pthread_cleanup_pop(0);
580 warning(ret,
"gwthread_join: error in pthread_cond_wait");
582 pthread_cond_destroy(&exit_cond);
610 pthread_cond_t exit_cond;
614 ret = pthread_cond_init(&exit_cond, NULL);
616 warning(ret,
"gwthread_join_every: cannot create condition variable.");
632 debug(
"gwlib.gwthread", 0,
633 "Waiting for %ld (%s) to terminate",
638 pthread_cleanup_push((
void(*)(
void*))pthread_mutex_unlock, &
threadtable_lock);
640 pthread_cleanup_pop(0);
642 warning(ret,
"gwthread_join_all: error in pthread_cond_wait");
646 pthread_cond_destroy(&exit_cond);
668 return (
long) getpid();
723 milliseconds = timeout * 1000;
724 if (milliseconds < 0)
730 error(errno,
"gwthread_pollfd: error in poll");
752 pollfds = gw_malloc((numfds + 1) *
sizeof(*pollfds));
756 memcpy(pollfds + 1, fds, numfds *
sizeof(*pollfds));
758 milliseconds = timeout * 1000;
759 if (milliseconds < 0)
762 ret =
poll(pollfds, numfds + 1, milliseconds);
765 error(errno,
"gwthread_poll: error in poll");
769 if (pollfds[0].revents)
773 memcpy(fds, pollfds + 1, numfds *
sizeof(*pollfds));
792 milliseconds = seconds * 1000;
793 if (milliseconds < 0)
798 if (errno != EINTR && errno != EAGAIN) {
799 warning(errno,
"gwthread_sleep: error in poll");
818 FD_ZERO(&fd_set_recv);
819 FD_SET(fd, &fd_set_recv);
822 ret = select(fd + 1, &fd_set_recv, NULL, NULL, NULL);
824 struct timeval timeout;
825 timeout.tv_sec = dseconds;
826 timeout.tv_usec = (dseconds - timeout.tv_sec) * 1000000;
828 ret = select(fd + 1, &fd_set_recv, NULL, NULL, &timeout);
832 if (errno != EINTR && errno != EAGAIN) {
833 warning(errno,
"gwthread_sleep_micro: error in select()");
837 if (FD_ISSET(fd, &fd_set_recv)) {
856 debug(
"gwlib.gwthread", 0,
"Thread %ld (%s) canceled.",
864 #ifndef BROKEN_PTHREADS 883 if (pthread_sigmask(SIG_BLOCK, NULL, &signal_set) != 0) {
884 warning(0,
"gwthread_dumpsigmask: Couldn't get signal mask.");
890 for (signum = 1; signum <= 32; signum++) {
891 if (!sigismember(&signal_set, signum)) {
893 "gwthread_dumpsigmask: Signal Number %d will be caught.",
902 #if defined(DARWIN_OLD) 903 static int pthread_sigmask()
void error(int err, const char *fmt,...)
void gwthread_join_all(void)
int socket_set_blocking(int fd, int blocking)
static struct threadinfo * threadtable[THREADTABLE_SIZE]
static void new_thread_cleanup(void *arg)
gw_assert(wtls_machine->packet_to_send !=NULL)
void gwlist_append(List *list, void *item)
void gwthread_join(long thread)
#define poll(fdarray, numfds, timeout)
void gwthread_sleep_micro(double dseconds)
int gwthread_shouldhandlesignal(int signal)
void gwthread_self_ids(long *tid, long *pid)
int gwthread_poll(struct pollfd *fds, long numfds, double timeout)
void gwthread_join_every(gwthread_func_t *func)
static long next_threadnumber
void gwthread_func_t(void *arg)
static long active_threads
long gwthread_self_pid(void)
void * gwlist_extract_first(List *list)
static struct threadinfo * getthreadinfo(void)
static void delete_threadinfo(void)
void gwthread_shutdown(void)
void warning(int err, const char *fmt,...)
static void alert_joiners(void)
void gwthread_sleep(double seconds)
static long fill_threadinfo(pthread_t id, const char *name, gwthread_func_t *func, struct threadinfo *ti)
static struct threadinfo mainthread
int gwthread_pollfd(int fd, int events, double timeout)
static pthread_mutex_t threadtable_lock
void debug(const char *place, int err, const char *fmt,...)
void gwthread_wakeup(long thread)
static pthread_key_t tsd_key
long gwthread_create_real(gwthread_func_t *func, const char *name, void *arg)
int gwthread_cancel(long thread)
static long spawn_thread(gwthread_func_t *func, const char *name, void *arg)
static void restore_user_signals(sigset_t *old_set)
void gwthread_wakeup_all(void)
static void flushpipe(int fd)
static int block_user_signals(sigset_t *old_set_storage)
static void * new_thread(void *arg)
int gwthread_dumpsigmask(void)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)