Commit c965b186 authored by Mark Andrews's avatar Mark Andrews

3353. [bug] Use a single task for task exclusive operations.

                        [RT #29872]
parent 77e3e9da
3353. [bug] Use a single task for task exclusive operations.
[RT #29872]
3352. [bug] Ensure that learned server attributes timeout of the
adb cache. [RT #29856]
......
......@@ -5603,11 +5603,13 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
/*
* Setup the server task, which is responsible for coordinating
* startup and shutdown of the server.
* startup and shutdown of the server, as well as all exclusive
* tasks.
*/
CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
"creating server task");
isc_task_setname(server->task, "server", server);
isc_taskmgr_setexcltask(ns_g_taskmgr, server->task);
CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
"isc_task_onshutdown");
CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
......
......@@ -111,6 +111,7 @@ struct dns_adb {
isc_taskmgr_t *taskmgr;
isc_task_t *task;
isc_task_t *excl;
isc_interval_t tick_interval;
int next_cleanbucket;
......@@ -1653,10 +1654,12 @@ new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
LOCK(&adb->namescntlock);
adb->namescnt++;
inc_adbstats(adb, dns_adbstats_namescnt);
if (!adb->grownames_sent && adb->namescnt > (adb->nnames * 8)) {
if (!adb->grownames_sent && adb->excl != NULL &&
adb->namescnt > (adb->nnames * 8))
{
isc_event_t *event = &adb->grownames;
inc_adb_irefcnt(adb);
isc_task_send(adb->task, &event);
isc_task_send(adb->excl, &event);
adb->grownames_sent = ISC_TRUE;
}
UNLOCK(&adb->namescntlock);
......@@ -1779,8 +1782,9 @@ new_adbentry(dns_adb_t *adb) {
LOCK(&adb->entriescntlock);
adb->entriescnt++;
inc_adbstats(adb, dns_adbstats_entriescnt);
if (!adb->growentries_sent &&
adb->entriescnt > (adb->nentries * 8)) {
if (!adb->growentries_sent && adb->growentries_sent &&
adb->entriescnt > (adb->nentries * 8))
{
isc_event_t *event = &adb->growentries;
inc_adb_irefcnt(adb);
isc_task_send(adb->task, &event);
......@@ -2356,6 +2360,7 @@ destroy(dns_adb_t *adb) {
adb->magic = 0;
isc_task_detach(&adb->task);
isc_task_detach(&adb->excl);
isc_mempool_destroy(&adb->nmp);
isc_mempool_destroy(&adb->nhmp);
......@@ -2439,6 +2444,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb->aimp = NULL;
adb->afmp = NULL;
adb->task = NULL;
adb->excl = NULL;
adb->mctx = NULL;
adb->view = view;
adb->taskmgr = taskmgr;
......@@ -2474,6 +2480,16 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
adb, NULL, NULL);
adb->grownames_sent = ISC_FALSE;
result = isc_taskmgr_excltask(adb->taskmgr, &adb->excl);
if (result != ISC_R_SUCCESS) {
DP(ISC_LOG_INFO, "adb: task-exclusive mode unavailable, "
"intializing table sizes to %u\n",
nbuckets[11]);
adb->nentries = nbuckets[11];
adb->nnames= nbuckets[11];
}
isc_mem_attach(mem, &adb->mctx);
result = isc_mutex_init(&adb->lock);
......@@ -2586,11 +2602,13 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
result = isc_task_create(adb->taskmgr, 0, &adb->task);
if (result != ISC_R_SUCCESS)
goto fail3;
isc_task_setname(adb->task, "ADB", adb);
result = isc_stats_create(adb->mctx, &view->adbstats, dns_adbstats_max);
if (result != ISC_R_SUCCESS)
goto fail3;
set_adbstat(adb, adb->nentries, dns_adbstats_nentries);
set_adbstat(adb, adb->nnames, dns_adbstats_nnames);
......
......@@ -153,6 +153,8 @@
#define isc_taskmgr_setmode isc__taskmgr_setmode
#define isc_taskmgr_mode isc__taskmgr_mode
#define isc_taskmgr_destroy isc__taskmgr_destroy
#define isc_taskmgr_setexcltask isc__taskmgr_setexcltask
#define isc_taskmgr_excltask isc__taskmgr_excltask
#define isc_task_beginexclusive isc__task_beginexclusive
#define isc_task_endexclusive isc__task_endexclusive
#define isc_task_setprivilege isc__task_setprivilege
......
......@@ -115,6 +115,8 @@ typedef struct isc_taskmgrmethods {
isc_result_t (*taskcreate)(isc_taskmgr_t *manager,
unsigned int quantum,
isc_task_t **taskp);
void (*setexcltask)(isc_taskmgr_t *mgr, isc_task_t *task);
isc_result_t (*excltask)(isc_taskmgr_t *mgr, isc_task_t **taskp);
} isc_taskmgrmethods_t;
typedef struct isc_taskmethods {
......@@ -759,6 +761,31 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp);
* have been freed.
*/
void
isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task);
/*%<
* Set a task which will be used for all task-exclusive operations.
*
* Requires:
*\li 'manager' is a valid task manager.
*
*\li 'task' is a valid task.
*/
isc_result_t
isc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp);
/*%<
* Attach '*taskp' to the task set by isc_taskmgr_getexcltask().
* This task should be used whenever running in task-exclusive mode,
* so as to prevent deadlock between two exclusive tasks.
*
* Requires:
*\li 'manager' is a valid task manager.
*\li taskp != NULL && *taskp == NULL
*/
#ifdef HAVE_LIBXML2
void
......
......@@ -158,6 +158,7 @@ struct isc__taskmgr {
isc_boolean_t pause_requested;
isc_boolean_t exclusive_requested;
isc_boolean_t exiting;
isc__task_t *excl;
#ifdef USE_SHARED_MANAGER
unsigned int refs;
#endif /* ISC_PLATFORM_USETHREADS */
......@@ -227,6 +228,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
......@@ -288,7 +293,9 @@ static isc_taskmgrmethods_t taskmgrmethods = {
isc__taskmgr_destroy,
isc__taskmgr_setmode,
isc__taskmgr_mode,
isc__task_create
isc__task_create,
isc__taskmgr_setexcltask,
isc__taskmgr_excltask
};
/***
......@@ -1411,6 +1418,7 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
manager->exclusive_requested = ISC_FALSE;
manager->pause_requested = ISC_FALSE;
manager->exiting = ISC_FALSE;
manager->excl = NULL;
isc_mem_attach(mctx, &manager->mctx);
......@@ -1494,6 +1502,12 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
* that the startup thread is sleeping on.
*/
/*
* 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
......@@ -1644,12 +1658,41 @@ isc__taskmgr_resume(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);
......
......@@ -201,6 +201,17 @@ isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag)
return (task->methods->purgeevents(task, sender, type, tag));
}
void
isc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task) {
REQUIRE(ISCAPI_TASK_VALID(task));
return (mgr->methods->setexcltask(mgr, task));
}
isc_result_t
isc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp) {
return (mgr->methods->excltask(mgr, taskp));
}
isc_result_t
isc_task_beginexclusive(isc_task_t *task) {
REQUIRE(ISCAPI_TASK_VALID(task));
......
......@@ -42,6 +42,7 @@ isc_log_t *lctx = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
isc_task_t *maintask = NULL;
int ncpus;
static isc_boolean_t hash_active = ISC_FALSE;
......@@ -63,6 +64,8 @@ static isc_logcategory_t categories[] = {
static void
cleanup_managers() {
if (maintask != NULL)
isc_task_destroy(&maintask);
if (socketmgr != NULL)
isc_socketmgr_destroy(&socketmgr);
if (taskmgr != NULL)
......@@ -81,6 +84,9 @@ create_managers() {
#endif
CHECK(isc_taskmgr_create(mctx, ncpus, 0, &taskmgr));
CHECK(isc_task_create(taskmgr, 0, &maintask));
isc_taskmgr_setexcltask(taskmgr, maintask);
CHECK(isc_timermgr_create(mctx, &timermgr));
CHECK(isc_socketmgr_create(mctx, &socketmgr));
return (ISC_R_SUCCESS);
......@@ -138,6 +144,8 @@ isc_test_begin(FILE *logfile, isc_boolean_t start_managers) {
void
isc_test_end() {
if (maintask != NULL)
isc_task_detach(&maintask);
if (taskmgr != NULL)
isc_taskmgr_destroy(&taskmgr);
if (lctx != NULL)
......
......@@ -140,7 +140,9 @@ isc__task_unsend
isc__task_unsendrange
isc__taskmgr_create
isc__taskmgr_destroy
isc__taskmgr_excltask
isc__taskmgr_mode
isc__taskmgr_setexcltask
isc__taskmgr_setmode
isc__timer_attach
isc__timer_create
......@@ -219,9 +221,9 @@ isc_event_free
isc_file_absolutepath
isc_file_basename
isc_file_exists
isc_file_getmodtime
isc_file_getsize
isc_file_getsizefd
isc_file_getmodtime
isc_file_isabsolute
isc_file_ischdiridempotent
isc_file_iscurrentdir
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment