diff options
Diffstat (limited to 'contrib/bind9/lib/isc/task.c')
-rw-r--r-- | contrib/bind9/lib/isc/task.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/contrib/bind9/lib/isc/task.c b/contrib/bind9/lib/isc/task.c index f4e1265..a5f6ef9 100644 --- a/contrib/bind9/lib/isc/task.c +++ b/contrib/bind9/lib/isc/task.c @@ -152,6 +152,7 @@ struct isc__taskmgr { unsigned int tasks_running; isc_boolean_t exclusive_requested; isc_boolean_t exiting; + isc__task_t *excl; #ifdef USE_SHARED_MANAGER unsigned int refs; #endif /* ISC_PLATFORM_USETHREADS */ @@ -221,6 +222,10 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, unsigned int default_quantum, isc_taskmgr_t **managerp); ISC_TASKFUNC_SCOPE void isc__taskmgr_destroy(isc_taskmgr_t **managerp); +ISC_TASKFUNC_SCOPE void +isc__taskmgr_setexcltask(isc_taskmgr_t *mgr0, isc_task_t *task0); +ISC_TASKFUNC_SCOPE isc_result_t +isc__taskmgr_excltask(isc_taskmgr_t *mgr0, isc_task_t **taskp); ISC_TASKFUNC_SCOPE isc_result_t isc__task_beginexclusive(isc_task_t *task); ISC_TASKFUNC_SCOPE void @@ -261,7 +266,9 @@ static struct isc__taskmethods { static isc_taskmgrmethods_t taskmgrmethods = { isc__taskmgr_destroy, - isc__task_create + isc__task_create, + isc__taskmgr_setexcltask, + isc__taskmgr_excltask }; /*** @@ -1262,6 +1269,7 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers, manager->tasks_running = 0; manager->exclusive_requested = ISC_FALSE; manager->exiting = ISC_FALSE; + manager->excl = NULL; isc_mem_attach(mctx, &manager->mctx); @@ -1344,6 +1352,12 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) { */ /* + * Detach the exclusive task before acquiring the manager lock + */ + if (manager->excl != NULL) + isc__task_detach((isc_task_t **) &manager->excl); + + /* * Unlike elsewhere, we're going to hold this lock a long time. * We need to do so, because otherwise the list of tasks could * change while we were traversing it. @@ -1440,12 +1454,41 @@ isc__taskmgr_dispatch(isc_taskmgr_t *manager0) { #endif /* USE_WORKER_THREADS */ +ISC_TASKFUNC_SCOPE void +isc__taskmgr_setexcltask(isc_taskmgr_t *mgr0, isc_task_t *task0) { + isc__taskmgr_t *mgr = (isc__taskmgr_t *) mgr0; + isc__task_t *task = (isc__task_t *) task0; + + REQUIRE(VALID_MANAGER(mgr)); + REQUIRE(VALID_TASK(task)); + if (mgr->excl != NULL) + isc__task_detach((isc_task_t **) &mgr->excl); + isc__task_attach(task0, (isc_task_t **) &mgr->excl); +} + +ISC_TASKFUNC_SCOPE isc_result_t +isc__taskmgr_excltask(isc_taskmgr_t *mgr0, isc_task_t **taskp) { + isc__taskmgr_t *mgr = (isc__taskmgr_t *) mgr0; + + REQUIRE(VALID_MANAGER(mgr)); + REQUIRE(taskp != NULL && *taskp == NULL); + + if (mgr->excl == NULL) + return (ISC_R_NOTFOUND); + + isc__task_attach((isc_task_t *) mgr->excl, taskp); + return (ISC_R_SUCCESS); +} + ISC_TASKFUNC_SCOPE isc_result_t isc__task_beginexclusive(isc_task_t *task0) { #ifdef USE_WORKER_THREADS isc__task_t *task = (isc__task_t *)task0; isc__taskmgr_t *manager = task->manager; + REQUIRE(task->state == task_state_running); + /* XXX: Require task == manager->excl? */ + LOCK(&manager->lock); if (manager->exclusive_requested) { UNLOCK(&manager->lock); |