]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3353. [bug] Use a single task for task exclusive operations.
authorMark Andrews <marka@isc.org>
Thu, 19 Jul 2012 13:00:21 +0000 (23:00 +1000)
committerMark Andrews <marka@isc.org>
Thu, 19 Jul 2012 13:00:21 +0000 (23:00 +1000)
                        [RT #29872]

CHANGES
bin/named/server.c
lib/dns/adb.c
lib/isc/include/isc/namespace.h
lib/isc/include/isc/task.h
lib/isc/task.c
lib/isc/task_api.c
lib/isc/tests/isctest.c
lib/isc/win32/libisc.def

diff --git a/CHANGES b/CHANGES
index da08d55cf5bc7403f9249db455bd919766586df2..d7ac8e7d5bcd0c55cca4bda9668ee3f38694a3ec 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+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]
 
index c2f1b07fa42c788b4e1aaf7142713818e24ea347..cb592dfffdf2ba34a2a1875cd551e7771565f12b 100644 (file)
@@ -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),
index 13432567f40068366681e5c1182e8321ac63e328..535624cdac5bfb47bcf3e021d213f8372d37b371 100644 (file)
@@ -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);
 
index 444e8143488c3971c3c320307383f648fb27cf2f..1dbb1a766bd6ee8ddb90a83afabe128eaa19d234 100644 (file)
 #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
index 594d80f3451099cdf244ef29402f88ba05817cd3..31234b7618fbff56b82c646854afecfdbcf09ad1 100644 (file)
@@ -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
index 5a6455de55d7fb1ad93f59315e6d7f36d1cdc6fe..ba2920b1637b61665c85c56ddc4bb218b12c71df 100644 (file)
@@ -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);
index 34510ff64c476630561fa888b93d02924fa5258b..f49ab321b2d3dda239ae44f84490d01d0e3deb67 100644 (file)
@@ -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));
index e118bbf2ad9e810316d1fdaaaaf4f723321971a9..41b09fce6e0b3d13e4be15631599983f52e44760 100644 (file)
@@ -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)
index e9000d237412a7ee11148f1ce3f71387c5ee5610..eee911e8ea035bd48e68034aeb82919d869d1ba3 100644 (file)
@@ -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