Index: bind9-git/lib/dns/dst_api.c =================================================================== --- bind9-git.orig/lib/dns/dst_api.c +++ bind9-git/lib/dns/dst_api.c @@ -105,6 +105,7 @@ static isc_result_t frombuffer(dns_name_ dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, + bool no_rdata, dst_key_t **keyp); static isc_result_t algorithm_status(unsigned int alg); @@ -740,6 +741,13 @@ isc_result_t dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { + return (dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp)); +} + +isc_result_t +dst_key_fromdns_ex(dns_name_t *name, dns_rdataclass_t rdclass, + isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, + dst_key_t **keyp) { uint8_t alg, proto; uint32_t flags, extflags; dst_key_t *key = NULL; @@ -768,7 +776,7 @@ dst_key_fromdns(dns_name_t *name, dns_rd } result = frombuffer(name, alg, flags, proto, rdclass, source, - mctx, &key); + mctx, no_rdata, &key); if (result != ISC_R_SUCCESS) return (result); key->key_id = id; @@ -790,7 +798,7 @@ dst_key_frombuffer(dns_name_t *name, uns REQUIRE(dst_initialized); result = frombuffer(name, alg, flags, protocol, rdclass, source, - mctx, &key); + mctx, false, &key); if (result != ISC_R_SUCCESS) return (result); @@ -1888,7 +1896,8 @@ computeid(dst_key_t *key) { static isc_result_t frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags, unsigned int protocol, dns_rdataclass_t rdclass, - isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) + isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, + dst_key_t **keyp) { dst_key_t *key; isc_result_t ret; @@ -1913,10 +1922,12 @@ frombuffer(dns_name_t *name, unsigned in return (DST_R_UNSUPPORTEDALG); } - ret = key->func->fromdns(key, source); - if (ret != ISC_R_SUCCESS) { - dst_key_free(&key); - return (ret); + if (!no_rdata) { + ret = key->func->fromdns(key, source); + if (ret != ISC_R_SUCCESS) { + dst_key_free(&key); + return (ret); + } } } Index: bind9-git/lib/dns/include/dns/validator.h =================================================================== --- bind9-git.orig/lib/dns/include/dns/validator.h +++ bind9-git/lib/dns/include/dns/validator.h @@ -160,6 +160,7 @@ struct dns_validator { unsigned int depth; unsigned int authcount; unsigned int authfail; + bool failed; isc_stdtime_t start; }; Index: bind9-git/lib/dns/include/dst/dst.h =================================================================== --- bind9-git.orig/lib/dns/include/dst/dst.h +++ bind9-git/lib/dns/include/dst/dst.h @@ -417,6 +417,10 @@ dst_key_tofile(const dst_key_t *key, int */ isc_result_t +dst_key_fromdns_ex(dns_name_t *name, dns_rdataclass_t rdclass, + isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, + dst_key_t **keyp); +isc_result_t dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass, isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); /*%< Index: bind9-git/lib/dns/resolver.c =================================================================== --- bind9-git.orig/lib/dns/resolver.c +++ bind9-git/lib/dns/resolver.c @@ -9075,7 +9075,7 @@ dns_resolver_create(dns_view_t *view, if (result != ISC_R_SUCCESS) goto cleanup_buckets; res->buckets[i].task = NULL; - result = isc_task_create(taskmgr, 0, &res->buckets[i].task); + result = isc_task_create(taskmgr, ISC_TASK_QUANTUM_SLOW, &res->buckets[i].task); if (result != ISC_R_SUCCESS) { DESTROYLOCK(&res->buckets[i].lock); goto cleanup_buckets; Index: bind9-git/lib/dns/validator.c =================================================================== --- bind9-git.orig/lib/dns/validator.c +++ bind9-git/lib/dns/validator.c @@ -1200,6 +1200,12 @@ create_validator(dns_validator_t *val, d * val->key at it. * * If val->key is non-NULL, this returns the next matching key. + * If val->key is already non-NULL, start searching from the next position in + * 'rdataset' to find the *next* key that could have signed 'siginfo', then + * set val->key to that. + * + * Returns ISC_R_SUCCESS if a possible matching key has been found, + * ISC_R_NOTFOUND if not. Any other value indicates error. */ static isc_result_t get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo, @@ -1209,56 +1215,58 @@ get_dst_key(dns_validator_t *val, dns_rd isc_buffer_t b; dns_rdata_t rdata = DNS_RDATA_INIT; dst_key_t *oldkey = val->key; - bool foundold; + bool no_rdata = false; - if (oldkey == NULL) - foundold = true; - else { - foundold = false; + if (oldkey == NULL) { + result = dns_rdataset_first(rdataset); + } else { + dst_key_free(&oldkey); val->key = NULL; + result = dns_rdataset_next(rdataset); + } + + if (result != ISC_R_SUCCESS) { + goto done; } - result = dns_rdataset_first(rdataset); - if (result != ISC_R_SUCCESS) - goto failure; do { dns_rdataset_current(rdataset, &rdata); isc_buffer_init(&b, rdata.data, rdata.length); isc_buffer_add(&b, rdata.length); INSIST(val->key == NULL); - result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b, - val->view->mctx, &val->key); + result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b, + val->view->mctx, no_rdata, + &val->key); if (result != ISC_R_SUCCESS) - goto failure; + goto done; if (siginfo->algorithm == (dns_secalg_t)dst_key_alg(val->key) && siginfo->keyid == (dns_keytag_t)dst_key_id(val->key) && + (dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) == + 0 && dst_key_iszonekey(val->key)) { - if (foundold) - /* - * This is the key we're looking for. - */ - return (ISC_R_SUCCESS); - else if (dst_key_compare(oldkey, val->key) == true) - { - foundold = true; - dst_key_free(&oldkey); + if (no_rdata) { + /* Retry with full key */ + dns_rdata_reset(&rdata); + dst_key_free(&val->key); + no_rdata = false; + continue; } + /* This is the key we're looking for. */ + goto done; } dst_key_free(&val->key); dns_rdata_reset(&rdata); result = dns_rdataset_next(rdataset); } while (result == ISC_R_SUCCESS); + + done: if (result == ISC_R_NOMORE) result = ISC_R_NOTFOUND; - failure: - if (oldkey != NULL) - dst_key_free(&oldkey); - return (result); } @@ -1626,37 +1634,13 @@ validate(dns_validator_t *val, bool resu continue; } - do { - vresult = verify(val, val->key, &rdata, - val->siginfo->keyid); - if (vresult == ISC_R_SUCCESS) - break; - if (val->keynode != NULL) { - dns_keynode_t *nextnode = NULL; - result = dns_keytable_findnextkeynode( - val->keytable, - val->keynode, - &nextnode); - dns_keytable_detachkeynode(val->keytable, - &val->keynode); - val->keynode = nextnode; - if (result != ISC_R_SUCCESS) { - val->key = NULL; - break; - } - val->key = dns_keynode_key(val->keynode); - if (val->key == NULL) - break; - } else { - if (get_dst_key(val, val->siginfo, val->keyset) - != ISC_R_SUCCESS) - break; - } - } while (1); - if (vresult != ISC_R_SUCCESS) + vresult = verify(val, val->key, &rdata, + val->siginfo->keyid); + if (vresult != ISC_R_SUCCESS) { + val->failed = true; validator_log(val, ISC_LOG_DEBUG(3), "failed to verify rdataset"); - else { + } else { dns_rdataset_trimttl(event->rdataset, event->sigrdataset, val->siginfo, val->start, @@ -1693,9 +1677,13 @@ validate(dns_validator_t *val, bool resu } else { validator_log(val, ISC_LOG_DEBUG(3), "verify failure: %s", - isc_result_totext(result)); + isc_result_totext(vresult)); resume = false; } + if (val->failed) { + result = ISC_R_NOMORE; + break; + } } if (result != ISC_R_NOMORE) { validator_log(val, ISC_LOG_DEBUG(3), Index: bind9-git/lib/dns/win32/libdns.def.in =================================================================== --- bind9-git.orig/lib/dns/win32/libdns.def.in +++ bind9-git/lib/dns/win32/libdns.def.in @@ -1435,6 +1435,7 @@ dst_key_format dst_key_free dst_key_frombuffer dst_key_fromdns +dst_key_fromdns_ex dst_key_fromfile dst_key_fromgssapi dst_key_fromlabel Index: bind9-git/lib/isc/include/isc/task.h =================================================================== --- bind9-git.orig/lib/isc/include/isc/task.h +++ bind9-git/lib/isc/include/isc/task.h @@ -98,8 +98,15 @@ ISC_LANG_BEGINDECLS ***/ typedef enum { - isc_taskmgrmode_normal = 0, - isc_taskmgrmode_privileged + isc_taskqueue_normal = 0, + isc_taskqueue_slow = 1, +} isc_taskqueue_t; + +#define ISC_TASK_QUANTUM_SLOW 1024 + +typedef enum { + isc_taskmgrmode_normal = 0, + isc_taskmgrmode_privileged } isc_taskmgrmode_t; /*% Task and task manager methods */ Index: bind9-git/lib/isc/task.c =================================================================== --- bind9-git.orig/lib/isc/task.c +++ bind9-git/lib/isc/task.c @@ -107,6 +107,7 @@ struct isc__task { isc_eventlist_t on_shutdown; unsigned int nevents; unsigned int quantum; + unsigned int qid; unsigned int flags; isc_stdtime_t now; isc_time_t tnow; @@ -141,11 +142,11 @@ struct isc__taskmgr { /* Locked by task manager lock. */ unsigned int default_quantum; LIST(isc__task_t) tasks; - isc__tasklist_t ready_tasks; - isc__tasklist_t ready_priority_tasks; + isc__tasklist_t ready_tasks[2]; + isc__tasklist_t ready_priority_tasks[2]; isc_taskmgrmode_t mode; #ifdef ISC_PLATFORM_USETHREADS - isc_condition_t work_available; + isc_condition_t work_available[2]; isc_condition_t exclusive_granted; isc_condition_t paused; #endif /* ISC_PLATFORM_USETHREADS */ @@ -247,13 +248,13 @@ isc_taskmgrmode_t isc__taskmgr_mode(isc_taskmgr_t *manager0); static inline bool -empty_readyq(isc__taskmgr_t *manager); +empty_readyq(isc__taskmgr_t *manager, isc_taskqueue_t qid); static inline isc__task_t * -pop_readyq(isc__taskmgr_t *manager); +pop_readyq(isc__taskmgr_t *manager, isc_taskqueue_t qid); static inline void -push_readyq(isc__taskmgr_t *manager, isc__task_t *task); +push_readyq(isc__taskmgr_t *manager, isc__task_t *task, isc_taskqueue_t qid); static struct isc__taskmethods { isc_taskmethods_t methods; @@ -324,7 +325,8 @@ task_finished(isc__task_t *task) { * any idle worker threads so they * can exit. */ - BROADCAST(&manager->work_available); + BROADCAST(&manager->work_available[isc_taskqueue_normal]); + BROADCAST(&manager->work_available[isc_taskqueue_slow]); } #endif /* USE_WORKER_THREADS */ UNLOCK(&manager->lock); @@ -362,7 +364,13 @@ isc__task_create(isc_taskmgr_t *manager0 INIT_LIST(task->events); INIT_LIST(task->on_shutdown); task->nevents = 0; - task->quantum = quantum; + if (quantum >= ISC_TASK_QUANTUM_SLOW) { + task->qid = isc_taskqueue_slow; + task->quantum = quantum - ISC_TASK_QUANTUM_SLOW; + } else { + task->qid = isc_taskqueue_normal; + task->quantum = quantum; + } task->flags = 0; task->now = 0; isc_time_settoepoch(&task->tnow); @@ -473,10 +481,12 @@ task_ready(isc__task_t *task) { XTRACE("task_ready"); LOCK(&manager->lock); - push_readyq(manager, task); + LOCK(&task->lock); + push_readyq(manager, task, task->qid); + UNLOCK(&task->lock); #ifdef USE_WORKER_THREADS if (manager->mode == isc_taskmgrmode_normal || has_privilege) - SIGNAL(&manager->work_available); + SIGNAL(&manager->work_available[task->qid]); #endif /* USE_WORKER_THREADS */ UNLOCK(&manager->lock); } @@ -947,13 +957,13 @@ isc__task_getcurrenttimex(isc_task_t *ta * Caller must hold the task manager lock. */ static inline bool -empty_readyq(isc__taskmgr_t *manager) { +empty_readyq(isc__taskmgr_t *manager, isc_taskqueue_t qid) { isc__tasklist_t queue; if (manager->mode == isc_taskmgrmode_normal) - queue = manager->ready_tasks; + queue = manager->ready_tasks[qid]; else - queue = manager->ready_priority_tasks; + queue = manager->ready_priority_tasks[qid]; return (EMPTY(queue)); } @@ -967,18 +977,18 @@ empty_readyq(isc__taskmgr_t *manager) { * Caller must hold the task manager lock. */ static inline isc__task_t * -pop_readyq(isc__taskmgr_t *manager) { +pop_readyq(isc__taskmgr_t *manager, isc_taskqueue_t qid) { isc__task_t *task; if (manager->mode == isc_taskmgrmode_normal) - task = HEAD(manager->ready_tasks); + task = HEAD(manager->ready_tasks[qid]); else - task = HEAD(manager->ready_priority_tasks); + task = HEAD(manager->ready_priority_tasks[qid]); if (task != NULL) { - DEQUEUE(manager->ready_tasks, task, ready_link); + DEQUEUE(manager->ready_tasks[qid], task, ready_link); if (ISC_LINK_LINKED(task, ready_priority_link)) - DEQUEUE(manager->ready_priority_tasks, task, + DEQUEUE(manager->ready_priority_tasks[qid], task, ready_priority_link); } @@ -992,16 +1002,16 @@ pop_readyq(isc__taskmgr_t *manager) { * Caller must hold the task manager lock. */ static inline void -push_readyq(isc__taskmgr_t *manager, isc__task_t *task) { - ENQUEUE(manager->ready_tasks, task, ready_link); +push_readyq(isc__taskmgr_t *manager, isc__task_t *task, isc_taskqueue_t qid) { + ENQUEUE(manager->ready_tasks[qid], task, ready_link); if ((task->flags & TASK_F_PRIVILEGED) != 0) - ENQUEUE(manager->ready_priority_tasks, task, + ENQUEUE(manager->ready_priority_tasks[qid], task, ready_priority_link); manager->tasks_ready++; } static void -dispatch(isc__taskmgr_t *manager) { +dispatch(isc__taskmgr_t *manager, isc_taskqueue_t qid) { isc__task_t *task; #ifndef USE_WORKER_THREADS unsigned int total_dispatch_count = 0; @@ -1080,26 +1090,26 @@ dispatch(isc__taskmgr_t *manager) { * If a pause has been requested, don't do any work * until it's been released. */ - while ((empty_readyq(manager) || manager->pause_requested || + while ((empty_readyq(manager, qid) || manager->pause_requested || manager->exclusive_requested) && !FINISHED(manager)) { XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_WAIT, "wait")); - WAIT(&manager->work_available, &manager->lock); + WAIT(&manager->work_available[qid], &manager->lock); XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK, ISC_MSG_AWAKE, "awake")); } #else /* USE_WORKER_THREADS */ if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM || - empty_readyq(manager)) + empty_readyq(manager, qid)) break; #endif /* USE_WORKER_THREADS */ XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK, ISC_MSG_WORKING, "working")); - task = pop_readyq(manager); + task = pop_readyq(manager, qid); if (task != NULL) { unsigned int dispatch_count = 0; bool done = false; @@ -1263,7 +1273,9 @@ dispatch(isc__taskmgr_t *manager) { * might even hurt rather than help. */ #ifdef USE_WORKER_THREADS - push_readyq(manager, task); + LOCK(&task->lock); + push_readyq(manager, task, qid); + UNLOCK(&task->lock); #else ENQUEUE(new_ready_tasks, task, ready_link); if ((task->flags & TASK_F_PRIVILEGED) != 0) @@ -1281,20 +1293,24 @@ dispatch(isc__taskmgr_t *manager) { * we're stuck. Automatically drop privileges at that * point and continue with the regular ready queue. */ - if (manager->tasks_running == 0 && empty_readyq(manager)) { + if (manager->tasks_running == 0 && empty_readyq(manager, isc_taskqueue_normal) && empty_readyq(manager, isc_taskqueue_slow)) { manager->mode = isc_taskmgrmode_normal; - if (!empty_readyq(manager)) - BROADCAST(&manager->work_available); + if (!empty_readyq(manager, isc_taskqueue_normal)) { + BROADCAST(&manager->work_available[isc_taskqueue_normal]); + } + if (!empty_readyq(manager, isc_taskqueue_slow)) { + BROADCAST(&manager->work_available[isc_taskqueue_slow]); + } } #endif } #ifndef USE_WORKER_THREADS - ISC_LIST_APPENDLIST(manager->ready_tasks, new_ready_tasks, ready_link); - ISC_LIST_APPENDLIST(manager->ready_priority_tasks, new_priority_tasks, + ISC_LIST_APPENDLIST(manager->ready_tasks[qid], new_ready_tasks, ready_link); + ISC_LIST_APPENDLIST(manager->ready_priority_tasks[qid], new_priority_tasks, ready_priority_link); manager->tasks_ready += tasks_ready; - if (empty_readyq(manager)) + if (empty_readyq(manager, qid)) manager->mode = isc_taskmgrmode_normal; #endif @@ -1306,13 +1322,37 @@ static isc_threadresult_t #ifdef _WIN32 WINAPI #endif -run(void *uap) { +run_normal(void *uap) { isc__taskmgr_t *manager = uap; XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_STARTING, "starting")); - dispatch(manager); + dispatch(manager, isc_taskqueue_normal); + + XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_EXITING, "exiting")); + +#ifdef OPENSSL_LEAKS + ERR_remove_state(0); +#endif + + return ((isc_threadresult_t)0); +} +#endif /* USE_WORKER_THREADS */ + +#ifdef USE_WORKER_THREADS +static isc_threadresult_t +#ifdef _WIN32 +WINAPI +#endif +run_slow(void *uap) { + isc__taskmgr_t *manager = uap; + + XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_STARTING, "starting")); + + dispatch(manager, isc_taskqueue_slow); XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, ISC_MSG_EXITING, "exiting")); @@ -1331,7 +1371,8 @@ manager_free(isc__taskmgr_t *manager) { #ifdef USE_WORKER_THREADS (void)isc_condition_destroy(&manager->exclusive_granted); - (void)isc_condition_destroy(&manager->work_available); + (void)isc_condition_destroy(&manager->work_available[isc_taskqueue_normal]); + (void)isc_condition_destroy(&manager->work_available[isc_taskqueue_slow]); (void)isc_condition_destroy(&manager->paused); isc_mem_free(manager->mctx, manager->threads); #endif /* USE_WORKER_THREADS */ @@ -1398,12 +1439,20 @@ isc__taskmgr_create(isc_mem_t *mctx, uns #ifdef USE_WORKER_THREADS manager->workers = 0; manager->threads = isc_mem_allocate(mctx, - workers * sizeof(isc_thread_t)); + 2 * workers * sizeof(isc_thread_t)); if (manager->threads == NULL) { result = ISC_R_NOMEMORY; goto cleanup_lock; } - if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) { + if (isc_condition_init(&manager->work_available[isc_taskqueue_normal]) != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "isc_condition_init() %s", + isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, + ISC_MSG_FAILED, "failed")); + result = ISC_R_UNEXPECTED; + goto cleanup_threads; + } + if (isc_condition_init(&manager->work_available[isc_taskqueue_slow]) != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_condition_init() %s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL, @@ -1432,8 +1481,10 @@ isc__taskmgr_create(isc_mem_t *mctx, uns default_quantum = DEFAULT_DEFAULT_QUANTUM; manager->default_quantum = default_quantum; INIT_LIST(manager->tasks); - INIT_LIST(manager->ready_tasks); - INIT_LIST(manager->ready_priority_tasks); + INIT_LIST(manager->ready_tasks[isc_taskqueue_normal]); + INIT_LIST(manager->ready_tasks[isc_taskqueue_slow]); + INIT_LIST(manager->ready_priority_tasks[isc_taskqueue_normal]); + INIT_LIST(manager->ready_priority_tasks[isc_taskqueue_slow]); manager->tasks_running = 0; manager->tasks_ready = 0; manager->exclusive_requested = false; @@ -1449,10 +1500,22 @@ isc__taskmgr_create(isc_mem_t *mctx, uns * Start workers. */ for (i = 0; i < workers; i++) { - if (isc_thread_create(run, manager, + if (isc_thread_create(run_normal, manager, + &manager->threads[manager->workers]) == + ISC_R_SUCCESS) { + char name[21]; /* thread name limit on Linux */ + snprintf(name, sizeof(name), "isc-worker%04u", i); + isc_thread_setname(manager->threads[manager->workers], + name); + manager->workers++; + started++; + } + } + for (; i < workers * 2; i++) { + if (isc_thread_create(run_slow, manager, &manager->threads[manager->workers]) == ISC_R_SUCCESS) { - char name[16]; /* thread name limit on Linux */ + char name[21]; /* thread name limit on Linux */ snprintf(name, sizeof(name), "isc-worker%04u", i); isc_thread_setname(manager->threads[manager->workers], name); @@ -1466,7 +1529,7 @@ isc__taskmgr_create(isc_mem_t *mctx, uns manager_free(manager); return (ISC_R_NOTHREADS); } - isc_thread_setconcurrency(workers); + isc_thread_setconcurrency(workers * 2); #endif /* USE_WORKER_THREADS */ #ifdef USE_SHARED_MANAGER manager->refs = 1; @@ -1481,7 +1544,8 @@ isc__taskmgr_create(isc_mem_t *mctx, uns cleanup_exclusivegranted: (void)isc_condition_destroy(&manager->exclusive_granted); cleanup_workavailable: - (void)isc_condition_destroy(&manager->work_available); + (void)isc_condition_destroy(&manager->work_available[isc_taskqueue_slow]); + (void)isc_condition_destroy(&manager->work_available[isc_taskqueue_normal]); cleanup_threads: isc_mem_free(mctx, manager->threads); cleanup_lock: @@ -1566,7 +1630,7 @@ isc__taskmgr_destroy(isc_taskmgr_t **man task = NEXT(task, link)) { LOCK(&task->lock); if (task_shutdown(task)) - push_readyq(manager, task); + push_readyq(manager, task, task->qid); UNLOCK(&task->lock); } #ifdef USE_WORKER_THREADS @@ -1575,7 +1639,8 @@ isc__taskmgr_destroy(isc_taskmgr_t **man * there's work left to do, and if there are already no tasks left * it will cause the workers to see manager->exiting. */ - BROADCAST(&manager->work_available); + BROADCAST(&manager->work_available[isc_taskqueue_normal]); + BROADCAST(&manager->work_available[isc_taskqueue_slow]); UNLOCK(&manager->lock); /* @@ -1636,7 +1701,8 @@ isc__taskmgr_ready(isc_taskmgr_t *manage return (false); LOCK(&manager->lock); - is_ready = !empty_readyq(manager); + is_ready = !empty_readyq(manager, isc_taskqueue_normal) || + !empty_readyq(manager, isc_taskqueue_slow); UNLOCK(&manager->lock); return (is_ready); @@ -1653,7 +1719,8 @@ isc__taskmgr_dispatch(isc_taskmgr_t *man if (manager == NULL) return (ISC_R_NOTFOUND); - dispatch(manager); + dispatch(manager, isc_taskqueue_normal); + dispatch(manager, isc_taskqueue_slow); return (ISC_R_SUCCESS); } @@ -1677,7 +1744,8 @@ isc__taskmgr_resume(isc_taskmgr_t *manag LOCK(&manager->lock); if (manager->pause_requested) { manager->pause_requested = false; - BROADCAST(&manager->work_available); + BROADCAST(&manager->work_available[isc_taskqueue_normal]); + BROADCAST(&manager->work_available[isc_taskqueue_slow]); } UNLOCK(&manager->lock); } @@ -1753,7 +1821,8 @@ isc__task_endexclusive(isc_task_t *task0 LOCK(&manager->lock); REQUIRE(manager->exclusive_requested); manager->exclusive_requested = false; - BROADCAST(&manager->work_available); + BROADCAST(&manager->work_available[isc_taskqueue_normal]); + BROADCAST(&manager->work_available[isc_taskqueue_slow]); UNLOCK(&manager->lock); #else UNUSED(task0); @@ -1779,10 +1848,10 @@ isc__task_setprivilege(isc_task_t *task0 LOCK(&manager->lock); if (priv && ISC_LINK_LINKED(task, ready_link)) - ENQUEUE(manager->ready_priority_tasks, task, + ENQUEUE(manager->ready_priority_tasks[task->qid], task, ready_priority_link); else if (!priv && ISC_LINK_LINKED(task, ready_priority_link)) - DEQUEUE(manager->ready_priority_tasks, task, + DEQUEUE(manager->ready_priority_tasks[task->qid], task, ready_priority_link); UNLOCK(&manager->lock); }