]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- speed up unbound (reports say it could be up to 10%), by reducing
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 24 Jan 2014 11:21:15 +0000 (11:21 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 24 Jan 2014 11:21:15 +0000 (11:21 +0000)
  lock contention on localzones.lock.  It is changed to an rwlock.

git-svn-id: file:///svn/unbound/trunk@3048 be551aaa-1e26-0410-a405-d3ace91eadb9

daemon/remote.c
doc/Changelog
libunbound/libunbound.c
services/localzone.c
services/localzone.h

index 9f93e6043f83739acc5cc4a8360920f660b66da6..0db1f48b8d57ce1735963fcbc2e3cfa90307b3ac 100644 (file)
@@ -981,7 +981,7 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
                free(nm);
                return;
        }
-       lock_quick_lock(&worker->daemon->local_zones->lock);
+       lock_rw_wrlock(&worker->daemon->local_zones->lock);
        if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen, 
                nmlabs, LDNS_RR_CLASS_IN))) {
                /* already present in tree */
@@ -989,17 +989,17 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
                z->type = t; /* update type anyway */
                lock_rw_unlock(&z->lock);
                free(nm);
-               lock_quick_unlock(&worker->daemon->local_zones->lock);
+               lock_rw_unlock(&worker->daemon->local_zones->lock);
                send_ok(ssl);
                return;
        }
        if(!local_zones_add_zone(worker->daemon->local_zones, nm, nmlen, 
                nmlabs, LDNS_RR_CLASS_IN, t)) {
-               lock_quick_unlock(&worker->daemon->local_zones->lock);
+               lock_rw_unlock(&worker->daemon->local_zones->lock);
                ssl_printf(ssl, "error out of memory\n");
                return;
        }
-       lock_quick_unlock(&worker->daemon->local_zones->lock);
+       lock_rw_unlock(&worker->daemon->local_zones->lock);
        send_ok(ssl);
 }
 
@@ -1013,13 +1013,13 @@ do_zone_remove(SSL* ssl, struct worker* worker, char* arg)
        struct local_zone* z;
        if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
                return;
-       lock_quick_lock(&worker->daemon->local_zones->lock);
+       lock_rw_wrlock(&worker->daemon->local_zones->lock);
        if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen, 
                nmlabs, LDNS_RR_CLASS_IN))) {
                /* present in tree */
                local_zones_del_zone(worker->daemon->local_zones, z);
        }
-       lock_quick_unlock(&worker->daemon->local_zones->lock);
+       lock_rw_unlock(&worker->daemon->local_zones->lock);
        free(nm);
        send_ok(ssl);
 }
@@ -1974,7 +1974,7 @@ do_list_local_zones(SSL* ssl, struct worker* worker)
        struct local_zones* zones = worker->daemon->local_zones;
        struct local_zone* z;
        char buf[257];
-       lock_quick_lock(&zones->lock);
+       lock_rw_rdlock(&zones->lock);
        RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
                lock_rw_rdlock(&z->lock);
                dname_str(z->name, buf);
@@ -1982,7 +1982,7 @@ do_list_local_zones(SSL* ssl, struct worker* worker)
                        local_zone_type2str(z->type));
                lock_rw_unlock(&z->lock);
        }
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
 }
 
 /** do the list_local_data command */
@@ -1995,7 +1995,7 @@ do_list_local_data(SSL* ssl, struct worker* worker)
        struct local_rrset* p;
        char* s = (char*)sldns_buffer_begin(worker->env.scratch_buffer);
        size_t slen = sldns_buffer_capacity(worker->env.scratch_buffer);
-       lock_quick_lock(&zones->lock);
+       lock_rw_rdlock(&zones->lock);
        RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
                lock_rw_rdlock(&z->lock);
                RBTREE_FOR(d, struct local_data*, &z->data) {
@@ -2016,7 +2016,7 @@ do_list_local_data(SSL* ssl, struct worker* worker)
                }
                lock_rw_unlock(&z->lock);
        }
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
 }
 
 /** tell other processes to execute the command */
index 1347b8f4413316f74fa707238e994ca3a58814ed..2cf92384ff93f9075e006a041db65f4d67bd306d 100644 (file)
@@ -2,6 +2,8 @@
        - Change unbound-event.h to use void* buffer, length idiom.
        - iana portlist updated.
        - unbound-event.h is installed if you configure --enable-event-api.
+       - speed up unbound (reports say it could be up to 10%), by reducing
+         lock contention on localzones.lock.  It is changed to an rwlock.
 
 21 January 2014: Wouter
        - Fix #547: no trustanchor written if filesystem full, fclose checked.
index dfcce0f8f4fbafcbce53c2c0bdf064920ee9ef36..d3a6fc2569c7a0566c57bbb052c68a950c2883ee 100644 (file)
@@ -1125,23 +1125,23 @@ int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
                return UB_SYNTAX;
        }
 
-       lock_quick_lock(&ctx->local_zones->lock);
+       lock_rw_wrlock(&ctx->local_zones->lock);
        if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 
                LDNS_RR_CLASS_IN))) {
                /* already present in tree */
                lock_rw_wrlock(&z->lock);
                z->type = t; /* update type anyway */
                lock_rw_unlock(&z->lock);
-               lock_quick_unlock(&ctx->local_zones->lock);
+               lock_rw_unlock(&ctx->local_zones->lock);
                free(nm);
                return UB_NOERROR;
        }
        if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs, 
                LDNS_RR_CLASS_IN, t)) {
-               lock_quick_unlock(&ctx->local_zones->lock);
+               lock_rw_unlock(&ctx->local_zones->lock);
                return UB_NOMEM;
        }
-       lock_quick_unlock(&ctx->local_zones->lock);
+       lock_rw_unlock(&ctx->local_zones->lock);
        return UB_NOERROR;
 }
 
@@ -1160,13 +1160,13 @@ int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name)
                return UB_SYNTAX;
        }
 
-       lock_quick_lock(&ctx->local_zones->lock);
+       lock_rw_wrlock(&ctx->local_zones->lock);
        if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs, 
                LDNS_RR_CLASS_IN))) {
                /* present in tree */
                local_zones_del_zone(ctx->local_zones, z);
        }
-       lock_quick_unlock(&ctx->local_zones->lock);
+       lock_rw_unlock(&ctx->local_zones->lock);
        free(nm);
        return UB_NOERROR;
 }
index 29df15faeb5a75d37246c3b6887f3a5a592ed10d..f1a9aaa9579d884e743998de8128bbae8c89b3ba 100644 (file)
@@ -59,7 +59,7 @@ local_zones_create(void)
        if(!zones)
                return NULL;
        rbtree_init(&zones->ztree, &local_zone_cmp);
-       lock_quick_init(&zones->lock);
+       lock_rw_init(&zones->lock);
        lock_protect(&zones->lock, &zones->ztree, sizeof(zones->ztree));
        /* also lock protects the rbnode's in struct local_zone */
        return zones;
@@ -78,7 +78,7 @@ local_zones_delete(struct local_zones* zones)
 {
        if(!zones)
                return;
-       lock_quick_destroy(&zones->lock);
+       lock_rw_destroy(&zones->lock);
        /* walk through zones and delete them all */
        traverse_postorder(&zones->ztree, lzdel, NULL);
        free(zones);
@@ -174,16 +174,16 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
        }
 
        /* add to rbtree */
-       lock_quick_lock(&zones->lock);
+       lock_rw_wrlock(&zones->lock);
        lock_rw_wrlock(&z->lock);
        if(!rbtree_insert(&zones->ztree, &z->node)) {
                log_warn("duplicate local-zone");
                lock_rw_unlock(&z->lock);
                local_zone_delete(z);
-               lock_quick_unlock(&zones->lock);
+               lock_rw_unlock(&zones->lock);
                return NULL;
        }
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
        return z;
 }
 
@@ -490,14 +490,14 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr)
                return 0;
        }
        labs = dname_count_size_labels(rr_name, &len);
-       lock_quick_lock(&zones->lock);
+       lock_rw_rdlock(&zones->lock);
        z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
        if(!z) {
-               lock_quick_unlock(&zones->lock);
+               lock_rw_unlock(&zones->lock);
                fatal_exit("internal error: no zone for rr %s", rr);
        }
        lock_rw_wrlock(&z->lock);
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
        free(rr_name);
        r = lz_enter_rr_into_zone(z, rr);
        lock_rw_unlock(&z->lock);
@@ -530,13 +530,13 @@ lz_exists(struct local_zones* zones, const char* name)
                log_err("bad name %s", name);
                return 0;
        }
-       lock_quick_lock(&zones->lock);
+       lock_rw_rdlock(&zones->lock);
        if(rbtree_search(&zones->ztree, &z.node)) {
-               lock_quick_unlock(&zones->lock);
+               lock_rw_unlock(&zones->lock);
                free(z.name);
                return 1;
        }
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
        free(z.name);
        return 0;
 }
@@ -693,7 +693,7 @@ init_parents(struct local_zones* zones)
 {
         struct local_zone* node, *prev = NULL, *p;
         int m;
-       lock_quick_lock(&zones->lock);
+       lock_rw_wrlock(&zones->lock);
         RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
                lock_rw_wrlock(&node->lock);
                 node->parent = NULL;
@@ -718,7 +718,7 @@ init_parents(struct local_zones* zones)
                 prev = node;
                lock_rw_unlock(&node->lock);
         }
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
 }
 
 /** enter implicit transparent zone for local-data: without local-zone: */
@@ -748,7 +748,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
                        return 0;
                }
                labs = dname_count_size_labels(rr_name, &len);
-               lock_quick_lock(&zones->lock);
+               lock_rw_rdlock(&zones->lock);
                if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) {
                        if(!have_name) {
                                dclass = rr_class;
@@ -763,7 +763,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
                                        /* process other classes later */
                                        free(rr_name);
                                        have_other_classes = 1;
-                                       lock_quick_unlock(&zones->lock);
+                                       lock_rw_unlock(&zones->lock);
                                        continue;
                                }
                                /* find smallest shared topdomain */
@@ -774,7 +774,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
                                        match = m;
                        }
                } else free(rr_name);
-               lock_quick_unlock(&zones->lock);
+               lock_rw_unlock(&zones->lock);
        }
        if(have_name) {
                uint8_t* n2;
@@ -919,7 +919,7 @@ local_zone_out(struct local_zone* z)
 void local_zones_print(struct local_zones* zones)
 {
        struct local_zone* z;
-       lock_quick_lock(&zones->lock);
+       lock_rw_rdlock(&zones->lock);
        log_info("number of auth zones %u", (unsigned)zones->ztree.count);
        RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
                lock_rw_rdlock(&z->lock);
@@ -956,7 +956,7 @@ void local_zones_print(struct local_zones* zones)
                local_zone_out(z);
                lock_rw_unlock(&z->lock);
        }
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
 }
 
 /** encode answer consisting of 1 rrset */
@@ -1106,15 +1106,15 @@ local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
        struct local_data* ld;
        struct local_zone* z;
        int r;
-       lock_quick_lock(&zones->lock);
+       lock_rw_rdlock(&zones->lock);
        z = local_zones_lookup(zones, qinfo->qname,
                qinfo->qname_len, labs, qinfo->qclass);
        if(!z) {
-               lock_quick_unlock(&zones->lock);
+               lock_rw_unlock(&zones->lock);
                return 0;
        }
        lock_rw_rdlock(&z->lock);
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
 
        if(local_data_answer(z, qinfo, edns, buf, temp, labs, &ld)) {
                lock_rw_unlock(&z->lock);
@@ -1238,20 +1238,22 @@ local_zones_add_RR(struct local_zones* zones, const char* rr)
                return 0;
        }
        labs = dname_count_size_labels(rr_name, &len);
-       lock_quick_lock(&zones->lock);
+       /* could first try readlock then get writelock if zone does not exist,
+        * but we do not add enough RRs (from multiple threads) to optimize */
+       lock_rw_wrlock(&zones->lock);
        z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
        if(!z) {
                z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
                        local_zone_transparent);
                if(!z) {
-                       lock_quick_unlock(&zones->lock);
+                       lock_rw_unlock(&zones->lock);
                        return 0;
                }
        } else {
                free(rr_name);
        }
        lock_rw_wrlock(&z->lock);
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
        r = lz_enter_rr_into_zone(z, rr);
        lock_rw_unlock(&z->lock);
        return r;
@@ -1297,15 +1299,15 @@ void local_zones_del_data(struct local_zones* zones,
        /* find zone */
        struct local_zone* z;
        struct local_data* d;
-       lock_quick_lock(&zones->lock);
+       lock_rw_rdlock(&zones->lock);
        z = local_zones_lookup(zones, name, len, labs, dclass);
        if(!z) {
                /* no such zone, we're done */
-               lock_quick_unlock(&zones->lock);
+               lock_rw_unlock(&zones->lock);
                return;
        }
        lock_rw_wrlock(&z->lock);
-       lock_quick_unlock(&zones->lock);
+       lock_rw_unlock(&zones->lock);
 
        /* find the domain */
        d = lz_find_node(z, name, len, labs);
index 68100ea7f6f77cc649bae60f3eb19b45f0216299..2db586750ff43d3e0883c12f5e6509c6eebf1bc8 100644 (file)
@@ -78,7 +78,7 @@ enum localzone_type {
  */
 struct local_zones {
        /** lock on the localzone tree */
-       lock_quick_t lock;
+       lock_rw_t lock;
        /** rbtree of struct local_zone */
        rbtree_t ztree;
 };