]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Added the isc_refcount_t type, which is a generic locked reference counter,
authorBrian Wellington <source@isc.org>
Tue, 30 Jan 2001 02:50:51 +0000 (02:50 +0000)
committerBrian Wellington <source@isc.org>
Tue, 30 Jan 2001 02:50:51 +0000 (02:50 +0000)
and make the rbtdb, zone, and view objects use it.
This should reduce contention on other locks, since (in the normal)
implementation, the reference count has its own lock.  In the future, it
should also be possible to implement an isc_refcount_t with atomic operations
instead of mutexes, which should also help performance.

lib/dns/include/dns/view.h
lib/dns/rbtdb.c
lib/dns/view.c
lib/dns/zone.c
lib/isc/include/isc/refcount.h [new file with mode: 0644]

index 0fe1bdf09f2b83d0ca193e5384233034ab8e8fa3..1461bfbb3af8bf9dbe7e736d17c87e870a834bbf 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.h,v 1.64 2001/01/12 22:22:17 bwelling Exp $ */
+/* $Id: view.h,v 1.65 2001/01/30 02:50:49 bwelling Exp $ */
 
 #ifndef DNS_VIEW_H
 #define DNS_VIEW_H 1
@@ -66,6 +66,7 @@
 #include <isc/event.h>
 #include <isc/mutex.h>
 #include <isc/net.h>
+#include <isc/refcount.h>
 #include <isc/rwlock.h>
 #include <isc/stdtime.h>
 
@@ -122,8 +123,10 @@ struct dns_view {
         */
        dns_acl_t *                     matchclients;
 
+       /* Locked by themselves. */
+       isc_refcount_t                  references;
+
        /* Locked by lock. */
-       unsigned int                    references;
        unsigned int                    weakrefs;
        unsigned int                    attributes;
        /* Under owner's locking control. */
index fee04e67e5b29859e79702e74caeb8fbdeae6254..58501e0f3d6aba58c9020ea83e45009aa51c6475 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: rbtdb.c,v 1.145 2001/01/24 02:40:19 halley Exp $ */
+/* $Id: rbtdb.c,v 1.146 2001/01/30 02:50:45 bwelling Exp $ */
 
 /*
  * Principal Author: Bob Halley
@@ -24,7 +24,9 @@
 #include <config.h>
 
 #include <isc/mem.h>
+#include <isc/mutex.h>
 #include <isc/random.h>
+#include <isc/refcount.h>
 #include <isc/rwlock.h>
 #include <isc/string.h>
 #include <isc/util.h>
@@ -157,7 +159,7 @@ typedef struct {
        rbtdb_nodelock_t *              node_locks;
        dns_rbtnode_t *                 origin_node;
        /* Locked by lock. */
-       unsigned int                    references;
+       isc_refcount_t                  references;
        unsigned int                    attributes;
        rbtdb_serial_t                  current_serial;
        rbtdb_serial_t                  least_serial;
@@ -316,10 +318,7 @@ attach(dns_db_t *source, dns_db_t **targetp) {
 
        REQUIRE(VALID_RBTDB(rbtdb));
 
-       LOCK(&rbtdb->lock);
-       REQUIRE(rbtdb->references > 0);
-       rbtdb->references++;
-       UNLOCK(&rbtdb->lock);
+       isc_refcount_increment(&rbtdb->references, NULL);
 
        *targetp = source;
 }
@@ -345,6 +344,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb) {
        isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,
                    rbtdb->node_lock_count * sizeof (rbtdb_nodelock_t));
        isc_rwlock_destroy(&rbtdb->tree_lock);
+       isc_refcount_destroy(&rbtdb->references);
        DESTROYLOCK(&rbtdb->lock);
        rbtdb->common.magic = 0;
        rbtdb->common.impmagic = 0;
@@ -382,18 +382,13 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t set_exiting) {
 static void
 detach(dns_db_t **dbp) {
        dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(*dbp);
-       isc_boolean_t maybe_free = ISC_FALSE;
+       unsigned int refs;
 
        REQUIRE(VALID_RBTDB(rbtdb));
 
-       LOCK(&rbtdb->lock);
-       REQUIRE(rbtdb->references > 0);
-       rbtdb->references--;
-       if (rbtdb->references == 0)
-               maybe_free = ISC_TRUE;
-       UNLOCK(&rbtdb->lock);
+       isc_refcount_decrement(&rbtdb->references, &refs);
 
-       if (maybe_free)
+       if (refs == 0)
                maybe_free_rbtdb(rbtdb, ISC_TRUE);
 
        *dbp = NULL;
@@ -4093,7 +4088,7 @@ dns_rbtdb_create
        /*
         * Misc. Initialization.
         */
-       rbtdb->references = 1;
+       isc_refcount_init(&rbtdb->references, 1);
        rbtdb->attributes = 0;
        rbtdb->secure = ISC_FALSE;
        rbtdb->overmem = ISC_FALSE;
index f485b8319316314c07bf91c2d373635045f7f068..ef8fd2af1cb0b374e5e04a8e0eaba34bfbafa10e 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.92 2001/01/12 22:22:16 bwelling Exp $ */
+/* $Id: view.c,v 1.93 2001/01/30 02:50:46 bwelling Exp $ */
 
 #include <config.h>
 
@@ -135,7 +135,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
        view->rdclass = rdclass;
        view->frozen = ISC_FALSE;
        view->task = NULL;
-       view->references = 1;
+       isc_refcount_init(&view->references, 1);
        view->weakrefs = 0;
        view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
                            DNS_VIEWATTR_REQSHUTDOWN);
@@ -217,7 +217,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
 static inline void
 destroy(dns_view_t *view) {
        REQUIRE(!ISC_LINK_LINKED(view, link));
-       REQUIRE(view->references == 0);
+       REQUIRE(isc_refcount_current(&view->references) == 0);
        REQUIRE(view->weakrefs == 0);
        REQUIRE(RESSHUTDOWN(view));
        REQUIRE(ADBSHUTDOWN(view));
@@ -260,6 +260,7 @@ destroy(dns_view_t *view) {
        dns_fwdtable_destroy(&view->fwdtable);
        isc_rwlock_destroy(&view->conflock);
        DESTROYLOCK(&view->lock);
+       isc_refcount_destroy(&view->references);
        isc_mem_free(view->mctx, view->name);
        isc_mem_put(view->mctx, view, sizeof *view);
 }
@@ -271,7 +272,8 @@ destroy(dns_view_t *view) {
 static isc_boolean_t
 all_done(dns_view_t *view) {
 
-       if (view->references == 0 && view->weakrefs == 0 &&
+       if (isc_refcount_current(&view->references) == 0 &&
+           view->weakrefs == 0 &&
            RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
                return (ISC_TRUE);
 
@@ -284,13 +286,7 @@ dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
        REQUIRE(DNS_VIEW_VALID(source));
        REQUIRE(targetp != NULL && *targetp == NULL);
 
-       LOCK(&source->lock);
-
-       INSIST(source->references > 0);
-       source->references++;
-       INSIST(source->references != 0);
-
-       UNLOCK(&source->lock);
+       isc_refcount_increment(&source->references, NULL);
 
        *targetp = source;
 }
@@ -298,17 +294,16 @@ dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
 static void
 view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
        dns_view_t *view;
+       unsigned int refs;
        isc_boolean_t done = ISC_FALSE;
 
        REQUIRE(viewp != NULL);
        view = *viewp;
        REQUIRE(DNS_VIEW_VALID(view));
 
-       LOCK(&view->lock);
-
-       INSIST(view->references > 0);
-       view->references--;
-       if (view->references == 0) {
+       isc_refcount_decrement(&view->references, &refs);
+       if (refs == 0) {
+               LOCK(&view->lock);
                if (!RESSHUTDOWN(view))
                        dns_resolver_shutdown(view->resolver);
                if (!ADBSHUTDOWN(view))
@@ -320,8 +315,8 @@ view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
                else
                        dns_zt_detach(&view->zonetable);
                done = all_done(view);
+               UNLOCK(&view->lock);
        }
-       UNLOCK(&view->lock);
 
        *viewp = NULL;
 
index 579ae331570832d291d9fb86d788315735ea16a8..aae98278ab6f73bfe79e51c2b6e33ccc30be741e 100644 (file)
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.c,v 1.300 2001/01/25 02:30:21 marka Exp $ */
+/* $Id: zone.c,v 1.301 2001/01/30 02:50:48 bwelling Exp $ */
 
 #include <config.h>
 
 #include <isc/file.h>
+#include <isc/mutex.h>
 #include <isc/print.h>
 #include <isc/random.h>
 #include <isc/ratelimiter.h>
+#include <isc/refcount.h>
 #include <isc/serial.h>
 #include <isc/string.h>
 #include <isc/taskpool.h>
@@ -127,13 +129,13 @@ struct dns_zone {
        isc_boolean_t           locked;
 #endif
        isc_mem_t               *mctx;
+       isc_refcount_t          erefs;
 
        /* Locked */
        dns_db_t                *db;
        dns_zonemgr_t           *zmgr;
        ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
        isc_timer_t             *timer;
-       unsigned int            erefs;
        unsigned int            irefs;
        dns_name_t              origin;
        char                    *masterfile;
@@ -462,7 +464,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->db = NULL;
        zone->zmgr = NULL;
        ISC_LINK_INIT(zone, link);
-       zone->erefs = 1;                /* Implicit attach. */
+       isc_refcount_init(&zone->erefs, 1);     /* Implicit attach. */
        zone->irefs = 0;
        dns_name_init(&zone->origin, NULL);
        zone->masterfile = NULL;
@@ -550,7 +552,7 @@ zone_free(dns_zone_t *zone) {
        isc_mem_t *mctx = NULL;
 
        REQUIRE(DNS_ZONE_VALID(zone));
-       REQUIRE(zone->erefs == 0);
+       REQUIRE(isc_refcount_current(&zone->erefs) == 0);
        REQUIRE(zone->irefs == 0);
        REQUIRE(!LOCKED_ZONE(zone));
 
@@ -602,6 +604,7 @@ zone_free(dns_zone_t *zone) {
 
        /* last stuff */
        DESTROYLOCK(&zone->lock);
+       isc_refcount_destroy(&zone->erefs);
        zone->magic = 0;
        mctx = zone->mctx;
        isc_mem_put(mctx, zone, sizeof *zone);
@@ -1282,7 +1285,7 @@ exit_check(dns_zone_t *zone) {
                /*
                 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
                 */
-               INSIST(zone->erefs == 0);
+               INSIST(isc_refcount_current(&zone->erefs) == 0);
                return (ISC_TRUE);
        }
        return (ISC_FALSE);
@@ -1436,29 +1439,24 @@ void
 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
        REQUIRE(DNS_ZONE_VALID(source));
        REQUIRE(target != NULL && *target == NULL);
-       LOCK_ZONE(source);
-       REQUIRE(source->erefs > 0);
-       source->erefs++;
-       INSIST(source->erefs != 0);
-       zone_debuglog(source, "dns_zone_attach", 10,
-                "eref = %d, irefs = %d", source->erefs, source->irefs);
-       UNLOCK_ZONE(source);
+       isc_refcount_increment(&source->erefs, NULL);
        *target = source;
 }
 
 void
 dns_zone_detach(dns_zone_t **zonep) {
        dns_zone_t *zone;
+       unsigned int refs;
        isc_boolean_t free_now = ISC_FALSE;
 
        REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
 
        zone = *zonep;
-       LOCK_ZONE(zone);
 
-       REQUIRE(zone->erefs > 0);
-       zone->erefs--;
-       if (zone->erefs == 0) {
+       isc_refcount_decrement(&zone->erefs, &refs);
+
+       if (refs == 0) {
+               LOCK_ZONE(zone);
                /*
                 * We just detached the last external reference.
                 */
@@ -1486,10 +1484,8 @@ dns_zone_detach(dns_zone_t **zonep) {
                        INSIST(zone->view == NULL);
                        free_now = ISC_TRUE;
                }
+               UNLOCK_ZONE(zone);
        }
-       zone_debuglog(zone, "dns_zone_detach", 10,
-                     "eref = %d, irefs = %d", zone->erefs, zone->irefs);
-       UNLOCK_ZONE(zone);
        *zonep = NULL;
        if (free_now)
                zone_free(zone);
@@ -1516,8 +1512,6 @@ zone_iattach(dns_zone_t *source, dns_zone_t **target) {
        source->irefs++;
        INSIST(source->irefs != 0);
        *target = source;
-       zone_debuglog(source, "zone_iattach", 10,
-                     "eref = %d, irefs = %d", source->erefs, source->irefs);
 }
 
 static void
@@ -1534,9 +1528,7 @@ zone_idetach(dns_zone_t **zonep) {
 
        INSIST(zone->irefs > 0);
        zone->irefs--;
-       zone_debuglog(zone, "zone_idetach", 10,
-                     "eref = %d, irefs = %d", zone->erefs, zone->irefs);
-       INSIST(zone->irefs + zone->erefs > 0);
+       INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
 }
 
 void
@@ -1551,8 +1543,6 @@ dns_zone_idetach(dns_zone_t **zonep) {
        LOCK_ZONE(zone);
        INSIST(zone->irefs > 0);
        zone->irefs--;
-       zone_debuglog(zone, "dns_zone_idetach", 10,
-                     "eref = %d, irefs = %d", zone->erefs, zone->irefs);
        free_needed = exit_check(zone);
        UNLOCK_ZONE(zone);
        if (free_needed)
@@ -3610,7 +3600,7 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
        UNUSED(task);
        REQUIRE(DNS_ZONE_VALID(zone));
        INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
-       INSIST(zone->erefs == 0);
+       INSIST(isc_refcount_current(&zone->erefs) == 0);
        zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
 
        /*
@@ -5640,7 +5630,7 @@ zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
         * XXXAG This should be done as soon as the zone goes on the
         * queue, using irefs.
         */
-       zone->erefs++;
+       isc_refcount_increment(&zone->erefs, NULL);
        isc_task_send(zone->task, &e);
        UNLOCK_ZONE(zone);
 
diff --git a/lib/isc/include/isc/refcount.h b/lib/isc/include/isc/refcount.h
new file mode 100644 (file)
index 0000000..20aeb19
--- /dev/null
@@ -0,0 +1,140 @@
+#ifndef ISC_REFERENCE_H
+#define ISC_REFERENCE_H 1
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+/*
+ * Implements a locked reference counter.  These functions may actually be
+ * implemented using macros, and implementations of these macros are below.
+ * The isc_refcount_t type should not be accessed directly, as its contents
+ * depend on the implementation.
+ */
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Function prototypes
+ */
+
+/*
+ * void
+ * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
+ *
+ * Initialize the reference counter.  There will be 'n' initial references.
+ *
+ * Requires:
+ *     ref != NULL
+ */
+
+/*
+ * void
+ * isc_refcount_destroy(isc_refcount_t *ref);
+ *
+ * Destroys a reference counter.
+ *
+ * Requires:
+ *     ref != NULL
+ *     The number of references is 0.
+ */
+
+/*
+ * void
+ * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp);
+ *
+ * Increments the reference count, returning the new value in targetp if it's
+ * not NULL.
+ *
+ * Requires:
+ *     ref != NULL.
+ */
+
+/*
+ * void
+ * isc_refcount_decrement(isc_refcount_t *ref, unsigned int *targetp);
+ *
+ * Decrements the reference count,  returning the new value in targetp if it's
+ * not NULL.
+ *
+ * Requires:
+ *     ref != NULL.
+ */
+
+
+/*
+ * Sample implementations
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+
+typedef struct isc_refcount {
+       int refs;
+       isc_mutex_t lock;
+} isc_refcount_t;
+
+#define isc_refcount_init(rp, n)                       \
+       do {                                            \
+               isc_result_t _r;                        \
+               (rp)->refs = (n);                       \
+               _r = isc_mutex_init(&(rp)->lock);       \
+               RUNTIME_CHECK(_r == ISC_R_SUCCESS);     \
+       } while (0)
+
+#define isc_refcount_destroy(rp)                       \
+       do {                                            \
+               REQUIRE((rp)->refs == 0);               \
+               DESTROYLOCK(&(rp)->lock);               \
+       } while (0)
+
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+#define isc_refcount_increment(rp, tp)                         \
+       do {                                                    \
+               LOCK(&(rp)->lock);                              \
+               REQUIRE((rp)->refs > 0);                        \
+               ++((rp)->refs);                                 \
+               if ((tp) != NULL)                               \
+                       *(unsigned int *)(tp) = ((rp)->refs);   \
+               UNLOCK(&(rp)->lock);                            \
+       } while (0)
+
+#define isc_refcount_decrement(rp, tp)                         \
+       do {                                                    \
+               LOCK(&(rp)->lock);                              \
+               REQUIRE((rp)->refs > 0);                        \
+               --((rp)->refs);                                 \
+               if ((tp) != NULL)                               \
+                       *(unsigned int *)(tp) = ((rp)->refs);   \
+               UNLOCK(&(rp)->lock);                            \
+       } while (0)
+
+#else
+
+typedef struct isc_refcount {
+       int refs;
+} isc_refcount_t;
+
+#define isc_refcount_init(rp, n) ((rp)->refs = (n))
+#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+#define isc_refcount_increment(rp, tp)                                 \
+       do {                                                            \
+               int _n = ++(rp)->refs;                                  \
+               if ((tp) != NULL)                                       \
+                       *(unsigned int *)(tp) = (unsigned int)(_n);     \
+       } while (0)
+
+#define isc_refcount_decrement(rp, tp)                                 \
+       do {                                                            \
+               int _n = --(rp)->refs;                                  \
+               if ((tp) != NULL)                                       \
+                       *(unsigned int *)(tp) = (unsigned int)(_n);     \
+       } while (0)
+
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_REFCOUNT_H */