From b20e0b6c53f8e1143fd413e5a5a630723925cfc8 Mon Sep 17 00:00:00 2001 From: zsxxsz Date: Thu, 20 Feb 2014 22:57:48 +0800 Subject: [PATCH] =?UTF-8?q?acl=203.0.16=20=E7=89=88=E6=9C=AC=E5=8F=91?= =?UTF-8?q?=E5=B8=83=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 该版本主要优化了线程池调度的性能,同时优化了多线程事件引擎的效率 --- changes.txt | 1 + lib_acl/changes.txt | 7 ++++ lib_acl/include/event/acl_events.h | 16 +++++++- lib_acl/include/master/acl_threads_params.h | 8 ++++ lib_acl/src/event/acl_events.c | 33 ++++++++++------ lib_acl/src/event/events.h | 1 + lib_acl/src/event/events_epoll_thr.c | 4 +- lib_acl/src/event/events_kernel.c | 2 +- lib_acl/src/event/events_poll_thr.c | 36 ++++++++++------- lib_acl/src/init/acl_init.c | 2 +- .../src/master/template/acl_threads_server.c | 13 ++++++- lib_acl/src/stdlib/acl_msg.c | 16 ++++---- lib_acl/src/thread/acl_pthread_pool.c | 39 ++++++++++++------- 13 files changed, 125 insertions(+), 53 deletions(-) diff --git a/changes.txt b/changes.txt index 2238eaaba..fe236aabf 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,6 @@ ޸ʷб ------------------------------------------------------------------------ +66) 2014.2.17 --- acl 3.0.16 汾 65) 2014.1.25 --- acl 3.0.15 汾 64) 2014.1.11 64.1) VC2008 ֧ diff --git a/lib_acl/changes.txt b/lib_acl/changes.txt index 9806a7748..7a7f9540c 100644 --- a/lib_acl/changes.txt +++ b/lib_acl/changes.txt @@ -1,6 +1,11 @@ ޸ʷб + ------------------------------------------------------------------------ +426) 2014.2.17 +426.1) feature: acl_event.c Ӻ acl_event_set_check_inter +¼ѭ̽ȫּʱ + 425) 2014.2.14 425.1) performance: acl_pthread_pool.c pthread_cond_signal pthread_mutex_unlock ֮󣬴Ӷ̵߳ȴ񱻴ʱ(Ϊ˷ֹ @@ -47,6 +52,8 @@ acl_aio_server.c, acl_udp_server.c Ϊÿ߳һ߳Ӷ֮߳ͻ ̳߳ص +------------------------------------------------------------------------ + 415) 2014.1.11 415.1) compile: ȥ ACL_MS_WINDOWS 궨壬WINDOWSͳһʹ WIN32 ʶ VC 뻷 diff --git a/lib_acl/include/event/acl_events.h b/lib_acl/include/event/acl_events.h index 3c80bdfbc..50afa1e46 100644 --- a/lib_acl/include/event/acl_events.h +++ b/lib_acl/include/event/acl_events.h @@ -147,11 +147,25 @@ ACL_API HWND acl_event_wmsg_hwnd(ACL_EVENT *eventp); */ ACL_API void acl_event_add_dog(ACL_EVENT *eventp); -ACL_API void acl_event_fire_hook(ACL_EVENT *eventp, +/** + * ¼ǰúͺô + * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ + * @param fire_begin {void (*)(ACL_EVENT*, void*)} ¼ͳһǰĻص + * @param fire_end {void (*)(ACL_EVENT*, void*)} ¼ͳһĻص + * @param ctx {void*} fire_begin / fire_end ĵڶ + */ +ACL_API void acl_event_set_fire_hook(ACL_EVENT *eventp, void (*fire_begin)(ACL_EVENT*, void*), void (*fire_end)(ACL_EVENT*, void*), void* ctx); +/** + * ¼ѭжʱ״̬ʱڲȱֵΪ 100 ms + * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ + * @param n {int} ʱʱ (뼶) + */ +ACL_API void acl_event_set_check_inter(ACL_EVENT *eventp, int n); + /** * ͷ¼ṹ * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ diff --git a/lib_acl/include/master/acl_threads_params.h b/lib_acl/include/master/acl_threads_params.h index a78b2a5a2..65325cdfa 100644 --- a/lib_acl/include/master/acl_threads_params.h +++ b/lib_acl/include/master/acl_threads_params.h @@ -116,6 +116,14 @@ extern int acl_var_threads_schedule_warn; #define ACL_DEF_THREADS_SCHEDULE_WAIT 50 extern int acl_var_threads_schedule_wait; +#define ACL_VAR_THREADS_CHECK_INTER "ioctl_check_inter" +#define ACL_DEF_THREADS_CHECK_INTER 100 +extern int acl_var_threads_check_inter; + +#define ACL_VAR_THREADS_QLEN_WARN "ioctl_qlen_warn" +#define ACL_DEF_THREADS_QLEN_WARN 0 +extern int acl_var_threads_qlen_warn; + #endif /* ACL_UNIX */ #ifdef __cplusplus diff --git a/lib_acl/src/event/acl_events.c b/lib_acl/src/event/acl_events.c index e17e1d450..c4108aaa8 100644 --- a/lib_acl/src/event/acl_events.c +++ b/lib_acl/src/event/acl_events.c @@ -45,16 +45,14 @@ static void event_init(ACL_EVENT *eventp, int fdsize, eventp->delay_sec = delay_sec + delay_usec / 1000000; eventp->delay_usec = delay_usec % 1000000; - /* - acl_ring_init(&eventp->used_ring); - acl_ring_init(&eventp->slot_ring); - */ acl_ring_init(&eventp->timer_head); eventp->timer_keep = 0; SET_TIME(eventp->present); SET_TIME(eventp->last_debug); + eventp->check_inter = 100000; /* default: 100 ms */ + if (eventp->init_fn) eventp->init_fn(eventp); } @@ -214,7 +212,8 @@ ACL_EVENT *acl_event_new_wmsg(unsigned int nMsg) #endif } -ACL_EVENT *acl_event_new(int event_mode, int use_thr, int delay_sec, int delay_usec) +ACL_EVENT *acl_event_new(int event_mode, int use_thr, + int delay_sec, int delay_usec) { const char *myname = "acl_event_new"; ACL_EVENT *eventp = NULL; @@ -222,10 +221,12 @@ ACL_EVENT *acl_event_new(int event_mode, int use_thr, int delay_sec, int delay_u if (use_thr) { switch (event_mode) { case ACL_EVENT_SELECT: - eventp = acl_event_new_select_thr(delay_sec, delay_usec); + eventp = acl_event_new_select_thr(delay_sec, + delay_usec); break; case ACL_EVENT_KERNEL: - eventp = acl_event_new_kernel_thr(delay_sec, delay_usec); + eventp = acl_event_new_kernel_thr(delay_sec, + delay_usec); break; case ACL_EVENT_POLL: eventp = acl_event_new_poll_thr(delay_sec, delay_usec); @@ -260,7 +261,13 @@ ACL_EVENT *acl_event_new(int event_mode, int use_thr, int delay_sec, int delay_u return eventp; } -void acl_event_fire_hook(ACL_EVENT *eventp, void (*fire_begin)(ACL_EVENT*, void*), +void acl_event_set_check_inter(ACL_EVENT *eventp, int n) +{ + eventp->check_inter = n * 1000; +} + +void acl_event_set_fire_hook(ACL_EVENT *eventp, + void (*fire_begin)(ACL_EVENT*, void*), void (*fire_end)(ACL_EVENT*, void*), void* ctx) { eventp->fire_begin = fire_begin; @@ -282,6 +289,7 @@ void acl_event_free(ACL_EVENT *eventp) acl_ring_detach(&timer->ring); acl_myfree(timer); } + acl_myfree(eventp->fdtabs); acl_myfree(eventp->fdtabs_ready); free_fn(eventp); @@ -300,7 +308,8 @@ void acl_event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream, if (sockfd == ACL_SOCKET_INVALID) acl_msg_fatal("%s(%d): sockfd(%d) invalid", myname, __LINE__, sockfd); - eventp->enable_read_fn(eventp, stream, read_timeout, callback, context); + eventp->enable_read_fn(eventp, stream, read_timeout, + callback, context); } void acl_event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, @@ -311,13 +320,15 @@ void acl_event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, if (sockfd == ACL_SOCKET_INVALID) acl_msg_fatal("%s(%d): sockfd(%d) invalid", myname, __LINE__, sockfd); - eventp->enable_write_fn(eventp, stream, write_timeout, callback, context); + eventp->enable_write_fn(eventp, stream, write_timeout, + callback, context); } void acl_event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *stream, int read_timeout, ACL_EVENT_NOTIFY_RDWR callback, void *context) { - eventp->enable_listen_fn(eventp, stream, read_timeout, callback, context); + eventp->enable_listen_fn(eventp, stream, read_timeout, + callback, context); } void acl_event_disable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream) diff --git a/lib_acl/src/event/events.h b/lib_acl/src/event/events.h index 64ed74edf..4b994a975 100644 --- a/lib_acl/src/event/events.h +++ b/lib_acl/src/event/events.h @@ -80,6 +80,7 @@ struct ACL_EVENT { /* ǰʱ(΢뼶) */ acl_int64 present; acl_int64 last_check; + acl_int64 check_inter; acl_int64 last_debug; /* ¼ȴʱ() */ int delay_sec; diff --git a/lib_acl/src/event/events_epoll_thr.c b/lib_acl/src/event/events_epoll_thr.c index fd62315e2..e8a9b8da1 100644 --- a/lib_acl/src/event/events_epoll_thr.c +++ b/lib_acl/src/event/events_epoll_thr.c @@ -343,7 +343,7 @@ static void event_loop(ACL_EVENT *eventp) eventp->fdcnt_ready = 0; - if (eventp->present - eventp->last_check >= 100000) { + if (eventp->present - eventp->last_check >= eventp->check_inter) { eventp->last_check = eventp->present; THREAD_LOCK(&event_thr->event.tb_mutex); @@ -371,7 +371,7 @@ static void event_loop(ACL_EVENT *eventp) if (nready < 0) { if (acl_last_error() != ACL_EINTR) - acl_msg_fatal("%s(%d), %s: event_loop: select: %s", + acl_msg_fatal("%s(%d), %s: event_loop: epoll: %s", __FILE__, __LINE__, myname, acl_last_serror()); goto TAG_DONE; } else if (nready == 0) diff --git a/lib_acl/src/event/events_kernel.c b/lib_acl/src/event/events_kernel.c index bc87c0964..bf8f6cb46 100644 --- a/lib_acl/src/event/events_kernel.c +++ b/lib_acl/src/event/events_kernel.c @@ -592,7 +592,7 @@ static void event_set_all(ACL_EVENT *eventp) eventp->fdcnt_ready = 0; - if (eventp->present - eventp->last_check >= 100000) { + if (eventp->present - eventp->last_check >= eventp->check_inter) { eventp->last_check = eventp->present; event_check_fds(eventp); } diff --git a/lib_acl/src/event/events_poll_thr.c b/lib_acl/src/event/events_poll_thr.c index 25bd2a4a3..efb1164ba 100644 --- a/lib_acl/src/event/events_poll_thr.c +++ b/lib_acl/src/event/events_poll_thr.c @@ -153,9 +153,9 @@ static void event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *stream, if (eventp->maxfd == ACL_SOCKET_INVALID || eventp->maxfd < sockfd) eventp->maxfd = sockfd; - acl_fdmap_add(event_thr->fdmap, sockfd, fdp); - THREAD_UNLOCK(&event_thr->event.tb_mutex); + + acl_fdmap_add(event_thr->fdmap, sockfd, fdp); } static void event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream, @@ -261,10 +261,10 @@ static void event_disable_readwrite(ACL_EVENT *eventp, ACL_VSTREAM *stream) event_thr->fds[fdp->fdidx] = event_thr->fds[eventp->fdcnt]; } - THREAD_UNLOCK(&event_thr->event.tb_mutex); - acl_fdmap_del(event_thr->fdmap, sockfd); + THREAD_UNLOCK(&event_thr->event.tb_mutex); + if (fdp->flag & EVENT_FDTABLE_FLAG_READ) stream->nrefer--; if (fdp->flag & EVENT_FDTABLE_FLAG_WRITE) @@ -314,24 +314,25 @@ static void event_loop(ACL_EVENT *eventp) ACL_EVENT_NOTIFY_TIME timer_fn; ACL_EVENT_TIMER *timer; void *timer_arg; - int delay, nready, i, revents; + int delay, nready, i, revents, fdcnt; ACL_EVENT_FDTABLE *fdp; acl_ring_init(&timer_ring); delay = eventp->delay_sec * 1000 + eventp->delay_usec / 1000; - if (delay <= 0) + if (delay < 0) delay = 100; /* 100 milliseconds at least */ SET_TIME(eventp->present); THREAD_LOCK(&event_thr->event.tm_mutex); /* - * Find out when the next timer would go off. Timer requests are sorted. - * If any timer is scheduled, adjust the delay appropriately. + * Find out when the next timer would go off. Timer requests + * are sorted. If any timer is scheduled, adjust the delay + * appropriately. */ if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { - int n = (int) (timer->when - eventp->present + 1000000 - 1) + int n = (int) (timer->when - eventp->present + 1000000 - 1) / 1000000; if (n <= 0) delay = 0; @@ -343,12 +344,13 @@ static void event_loop(ACL_EVENT *eventp) eventp->fdcnt_ready = 0; - if (eventp->present - eventp->last_check >= 100000) { + if (eventp->present - eventp->last_check >= eventp->check_inter) { eventp->last_check = eventp->present; THREAD_LOCK(&event_thr->event.tb_mutex); if (event_thr_prepare(eventp) == 0) { + THREAD_UNLOCK(&event_thr->event.tb_mutex); if (eventp->fdcnt_ready == 0) @@ -358,7 +360,9 @@ static void event_loop(ACL_EVENT *eventp) goto TAG_DONE; } - memcpy(event_thr->fdset, event_thr->fds, eventp->fdcnt); + memcpy(event_thr->fdset, event_thr->fds, + eventp->fdcnt * sizeof(struct pollfd)); + fdcnt = eventp->fdcnt; THREAD_UNLOCK(&event_thr->event.tb_mutex); @@ -367,24 +371,26 @@ static void event_loop(ACL_EVENT *eventp) } else { THREAD_LOCK(&event_thr->event.tb_mutex); - memcpy(event_thr->fdset, event_thr->fds, eventp->fdcnt); + memcpy(event_thr->fdset, event_thr->fds, + eventp->fdcnt * sizeof(struct pollfd)); + fdcnt = eventp->fdcnt; THREAD_UNLOCK(&event_thr->event.tb_mutex); } event_thr->event.blocked = 1; - nready = poll(event_thr->fdset, eventp->fdcnt, delay); + nready = poll(event_thr->fdset, fdcnt, delay); event_thr->event.blocked = 0; if (nready < 0) { if (acl_last_error() != ACL_EINTR) - acl_msg_fatal("%s(%d), %s: event_loop: select: %s", + acl_msg_fatal("%s(%d), %s: event_loop: poll: %s", __FILE__, __LINE__, myname, acl_last_serror()); goto TAG_DONE; } else if (nready == 0) goto TAG_DONE; - for (i = 0; i < eventp->fdcnt; i++) { + for (i = 0; i < fdcnt; i++) { fdp = acl_fdmap_ctx(event_thr->fdmap, event_thr->fdset[i].fd); if (fdp == NULL || fdp->stream == NULL) continue; diff --git a/lib_acl/src/init/acl_init.c b/lib_acl/src/init/acl_init.c index a48494ea9..cc9c95648 100644 --- a/lib_acl/src/init/acl_init.c +++ b/lib_acl/src/init/acl_init.c @@ -24,7 +24,7 @@ #include "init.h" -static char *version = "lib_acl_3.0.12"; +static char *version = "lib_acl_3.0.16"; const char *acl_version(void) { diff --git a/lib_acl/src/master/template/acl_threads_server.c b/lib_acl/src/master/template/acl_threads_server.c index 74acd13f1..529b7362e 100644 --- a/lib_acl/src/master/template/acl_threads_server.c +++ b/lib_acl/src/master/template/acl_threads_server.c @@ -79,6 +79,8 @@ int acl_var_threads_enable_core; int acl_var_threads_max_debug; int acl_var_threads_status_notify; int acl_var_threads_batadd; +int acl_var_threads_check_inter; +int acl_var_threads_qlen_warn; int acl_var_threads_schedule_warn; int acl_var_threads_schedule_wait; @@ -101,8 +103,10 @@ static ACL_CONFIG_INT_TABLE __conf_int_tab[] = { { ACL_VAR_THREADS_MAX_DEBUG, ACL_DEF_THREADS_MAX_DEBUG, &acl_var_threads_max_debug, 0, 0 }, { ACL_VAR_THREADS_STATUS_NOTIFY, ACL_DEF_THREADS_STATUS_NOTIFY, &acl_var_threads_status_notify, 0, 0 }, { ACL_VAR_THREADS_BATADD, ACL_DEF_THREADS_BATADD, &acl_var_threads_batadd, 0, 0 }, + { ACL_VAR_THREADS_QLEN_WARN, ACL_DEF_THREADS_QLEN_WARN, &acl_var_threads_qlen_warn, 0, 0 }, { ACL_VAR_THREADS_SCHEDULE_WARN, ACL_DEF_THREADS_SCHEDULE_WARN, &acl_var_threads_schedule_warn, 0, 0 }, { ACL_VAR_THREADS_SCHEDULE_WAIT, ACL_DEF_THREADS_SCHEDULE_WAIT, &acl_var_threads_schedule_wait, 0, 0 }, + { ACL_VAR_THREADS_CHECK_INTER, ACL_DEF_THREADS_CHECK_INTER, &acl_var_threads_check_inter, 0, 0 }, { 0, 0, 0, 0, 0 }, }; @@ -741,9 +745,16 @@ static ACL_EVENT *event_open(int event_mode, acl_pthread_pool_t *threads) /* set the event fire begin and fire end callback */ if (acl_var_threads_batadd) - acl_event_fire_hook(event, event_fire_begin, + acl_event_set_fire_hook(event, event_fire_begin, event_fire_end, threads); + if (acl_var_threads_check_inter > 0) + acl_event_set_check_inter(event, acl_var_threads_check_inter); + + if (acl_var_threads_qlen_warn > 0) + acl_pthread_pool_set_qlen_warn(threads, + acl_var_threads_qlen_warn); + /* * Running as a semi-resident server. Service connection requests. * Terminate when we have serviced a sufficient number of clients, diff --git a/lib_acl/src/stdlib/acl_msg.c b/lib_acl/src/stdlib/acl_msg.c index 3c62354bd..b611b3a40 100644 --- a/lib_acl/src/stdlib/acl_msg.c +++ b/lib_acl/src/stdlib/acl_msg.c @@ -92,7 +92,7 @@ void acl_msg_open2(ACL_VSTREAM *fp, const char *info_pre) void acl_msg_open(const char *log_file, const char *info_pre) { - char where[] = "acl_msg_open"; + const char *myname = "acl_msg_open"; int ret; if (log_file == NULL || *log_file == 0 @@ -111,13 +111,12 @@ void acl_msg_open(const char *log_file, const char *info_pre) __msg_ctx = NULL; ret = acl_open_log(log_file, info_pre); } - } else { + } else ret = acl_open_log(log_file, info_pre); - } + if (ret < 0) { - char ebuf[256]; printf("%s: can't open log file=%s, info_pre=%s,%s\n", - where, log_file, info_pre, acl_last_strerror(ebuf, sizeof(ebuf))); + myname, log_file, info_pre, acl_last_serror()); __log_open_flag = 0; __open_fn = NULL; __write_fn = NULL; @@ -446,7 +445,8 @@ const char *acl_strerror(unsigned int errnum, char *buffer, int size) return NULL; } - L = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, + L = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, errnum, 0, @@ -513,7 +513,9 @@ const char *acl_last_serror(void) if (buf == NULL) { buf = acl_mymalloc(__buf_size); acl_pthread_setspecific(__errbuf_key, buf); - if ((unsigned long) acl_pthread_self() == acl_main_thread_self()) { + if ((unsigned long) acl_pthread_self() + == acl_main_thread_self()) + { __main_buf = buf; atexit(main_free_buf); } diff --git a/lib_acl/src/thread/acl_pthread_pool.c b/lib_acl/src/thread/acl_pthread_pool.c index 8c6917b5a..e02f02254 100644 --- a/lib_acl/src/thread/acl_pthread_pool.c +++ b/lib_acl/src/thread/acl_pthread_pool.c @@ -25,7 +25,9 @@ #endif #define ACL_PTHREAD_POOL_VALID 0x0decca62 -#define SEC_TO_NSEC 1000000000 +#define SEC_TO_NS 1000000000 +#define SEC_TO_MS 1000 +#define MS_TO_NS 1000000 #define SET_TIME(x) do { \ struct timeval t; \ @@ -53,6 +55,8 @@ typedef struct thread_worker { int quit; /* if thread need quit ? */ int idle; /* thread wait timeout */ acl_int64 wait_base; /* once wait: nanosecond */ + acl_int64 wait_sec; /* once wait: second */ + acl_int64 wait_nsec; /* once wait: nanosecond */ acl_int64 wait_count; /* timeout of total wait */ acl_pthread_job_t *job_first; /* thread's work queue first */ acl_pthread_job_t *job_last; /* thread's work queue last */ @@ -208,8 +212,13 @@ static thread_worker *worker_create(acl_pthread_pool_t *thr_pool) thr->id = (unsigned long) acl_pthread_self(); thr->idle = thr_pool->idle_timeout; if (thr->idle > 0 && thr_pool->schedule_wait > 0) { - thr->wait_base = thr_pool->schedule_wait * 1000000; - thr->wait_count = SEC_TO_NSEC/thr->wait_base * thr->idle; + thr->wait_sec = thr_pool->schedule_wait / SEC_TO_MS; + thr->wait_nsec = (thr_pool->schedule_wait * MS_TO_NS) + % SEC_TO_NS; + thr->wait_count = (SEC_TO_MS * thr->idle) + / thr_pool->schedule_wait; + if (thr->wait_count == 0) + thr->idle = 0; } else thr->idle = 0; @@ -319,6 +328,9 @@ static int worker_wait(acl_pthread_pool_t *thr_pool, thread_worker *thr) { const char *myname = "worker_wait"; int status, idle_count = 0; + struct timespec timeout; + struct timeval tv; + acl_int64 n; while (1) { @@ -338,18 +350,13 @@ static int worker_wait(acl_pthread_pool_t *thr_pool, thread_worker *thr) thr_pool->idle++; if (thr->idle > 0) { - struct timespec timeout; - struct timeval tv; - acl_int64 n; - gettimeofday(&tv, NULL); - timeout.tv_sec = tv.tv_sec; - n = tv.tv_usec * 1000 + thr->wait_base; - if (n >= SEC_TO_NSEC) { + timeout.tv_sec = tv.tv_sec + (time_t) thr->wait_sec; + n = tv.tv_usec * 1000 + thr->wait_nsec; + if (n >= SEC_TO_NS) { timeout.tv_sec += 1; - timeout.tv_nsec = (long) n - SEC_TO_NSEC; - } - else + timeout.tv_nsec = (long) n - SEC_TO_NS; + } else timeout.tv_nsec = (long) n; status = acl_pthread_cond_timedwait(&thr->cond->cond, @@ -438,6 +445,7 @@ static void *worker_thread(void* arg) } for (;;) { + /* handle thread self's job first */ if (thr->job_first != NULL) { job = thr->job_first; @@ -450,7 +458,7 @@ static void *worker_thread(void* arg) } /* then handle thread pool's job */ - if (thr_pool->job_first != NULL) { + else if (thr_pool->job_first != NULL) { job = thr_pool->job_first; thr_pool->job_first = job->next; if (thr_pool->job_last == job) @@ -463,6 +471,9 @@ static void *worker_thread(void* arg) if (thr->job_first != NULL || thr_pool->job_first != NULL) continue; + else if (thr_pool->quit) + break; + else if (worker_wait(thr_pool, thr) > 0) continue;