]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Make hazard pointers max_threads configurable at runtime.
authorWitold Kręcicki <wpk@isc.org>
Thu, 12 Dec 2019 22:41:57 +0000 (23:41 +0100)
committerWitold Kręcicki <wpk@isc.org>
Tue, 14 Jan 2020 20:26:57 +0000 (21:26 +0100)
hp implementation requires an object for each thread accessing
a hazard pointer. previous implementation had a hardcoded
HP_MAX_THREAD value of 128, which failed on machines with lots of
CPU cores (named uses 3n threads). We make isc__hp_max_threads
configurable at startup, with the value set to 4*named_g_cpus.
It's also important for this value not to be too big as we do
linear searches on a list.

bin/named/main.c
lib/isc/hp.c
lib/isc/include/isc/hp.h
lib/isc/win32/libisc.def.in

index 9d8e1aeedc4375b7875ae1034ee8223abf0dda12..1e00f016a4f4fa12aa971ca422f38e8d1922b193 100644 (file)
@@ -23,6 +23,7 @@
 #include <isc/dir.h>
 #include <isc/file.h>
 #include <isc/hash.h>
+#include <isc/hp.h>
 #include <isc/httpd.h>
 #include <isc/netmgr.h>
 #include <isc/os.h>
@@ -907,6 +908,12 @@ create_managers(void) {
                      "using %u UDP listener%s per interface",
                      named_g_udpdisp, named_g_udpdisp == 1 ? "" : "s");
 
+       /*
+        * We have ncpus network threads, ncpus worker threads, ncpus
+        * old network threads - make it 4x just to be safe. The memory
+        * impact is neglible.
+        */
+       isc_hp_init(4*named_g_cpus);
        named_g_nm = isc_nm_start(named_g_mctx, named_g_cpus);
        if (named_g_nm == NULL) {
                UNEXPECTED_ERROR(__FILE__, __LINE__,
index 4bdd23c284742fe16bec4e628303d50256e30f8c..ca3a7af539828b2189dba1a570896b587b1fcfec 100644 (file)
 #include <isc/thread.h>
 
 #define HP_MAX_THREADS 128
+static int isc__hp_max_threads = HP_MAX_THREADS;
 #define HP_MAX_HPS 4                   /* This is named 'K' in the HP paper */
 #define CLPAD (128 / sizeof(uintptr_t))
 #define HP_THRESHOLD_R 0               /* This is named 'R' in the HP paper */
 
 /* Maximum number of retired objects per thread */
-#define MAX_RETIRED (HP_MAX_THREADS * HP_MAX_HPS)
+static int isc__hp_max_retired = HP_MAX_THREADS * HP_MAX_HPS;
 
 #define TID_UNKNOWN -1
 
@@ -69,14 +70,14 @@ ISC_THREAD_LOCAL int tid_v = TID_UNKNOWN;
 
 typedef struct retirelist {
        int                     size;
-       uintptr_t               list[MAX_RETIRED];
+       uintptr_t               *list;
 } retirelist_t;
 
 struct isc_hp {
        int                     max_hps;
        isc_mem_t               *mctx;
-       atomic_uintptr_t        *hp[HP_MAX_THREADS];
-       retirelist_t            *rl[HP_MAX_THREADS];
+       atomic_uintptr_t        **hp;
+       retirelist_t            **rl;
        isc_hp_deletefunc_t     *deletefunc;
 };
 
@@ -84,12 +85,18 @@ static inline int
 tid() {
        if (tid_v == TID_UNKNOWN) {
                tid_v = atomic_fetch_add(&tid_v_base, 1);
-               REQUIRE(tid_v < HP_MAX_THREADS);
+               REQUIRE(tid_v < isc__hp_max_threads);
        }
 
        return (tid_v);
 }
 
+void
+isc_hp_init(int max_threads) {
+       isc__hp_max_threads = max_threads;
+       isc__hp_max_retired = max_threads * HP_MAX_HPS;
+}
+
 isc_hp_t *
 isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
        isc_hp_t *hp = isc_mem_get(mctx, sizeof(*hp));
@@ -105,7 +112,10 @@ isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
 
        isc_mem_attach(mctx, &hp->mctx);
 
-       for (int i = 0; i < HP_MAX_THREADS; i++) {
+       hp->hp = isc_mem_get(mctx, isc__hp_max_threads * sizeof(hp->hp[0]));
+       hp->rl = isc_mem_get(mctx, isc__hp_max_threads * sizeof(hp->rl[0]));
+
+       for (int i = 0; i < isc__hp_max_threads; i++) {
                hp->hp[i] = isc_mem_get(mctx, CLPAD * 2 * sizeof(hp->hp[i][0]));
                hp->rl[i] = isc_mem_get(mctx, sizeof(*hp->rl[0]));
                *hp->rl[i] = (retirelist_t) { .size = 0 };
@@ -113,6 +123,7 @@ isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
                for (int j = 0; j < hp->max_hps; j++) {
                        atomic_init(&hp->hp[i][j], 0);
                }
+               hp->rl[i]->list = isc_mem_get(hp->mctx, isc__hp_max_retired * sizeof(uintptr_t));
        }
 
        return (hp);
@@ -120,7 +131,7 @@ isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc) {
 
 void
 isc_hp_destroy(isc_hp_t *hp) {
-       for (int i = 0; i < HP_MAX_THREADS; i++) {
+       for (int i = 0; i < isc__hp_max_threads; i++) {
                isc_mem_put(hp->mctx, hp->hp[i],
                            CLPAD * 2 * sizeof(uintptr_t));
 
@@ -128,9 +139,11 @@ isc_hp_destroy(isc_hp_t *hp) {
                        void *data = (void *)hp->rl[i]->list[j];
                        hp->deletefunc(data);
                }
-
+               isc_mem_put(hp->mctx, hp->rl[i]->list, isc__hp_max_retired * sizeof(uintptr_t));
                isc_mem_put(hp->mctx, hp->rl[i], sizeof(*hp->rl[0]));
        }
+       isc_mem_put(hp->mctx, hp->hp, isc__hp_max_threads * sizeof(hp->hp[0]));
+       isc_mem_put(hp->mctx, hp->rl, isc__hp_max_threads * sizeof(hp->rl[0]));
 
        isc_mem_putanddetach(&hp->mctx, hp, sizeof(*hp));
 }
@@ -172,7 +185,7 @@ isc_hp_protect_release(isc_hp_t *hp, int ihp, atomic_uintptr_t ptr) {
 void
 isc_hp_retire(isc_hp_t *hp, uintptr_t ptr) {
        hp->rl[tid()]->list[hp->rl[tid()]->size++] = ptr;
-       INSIST(hp->rl[tid()]->size < MAX_RETIRED);
+       INSIST(hp->rl[tid()]->size < isc__hp_max_retired);
 
        if (hp->rl[tid()]->size < HP_THRESHOLD_R) {
                return;
@@ -182,7 +195,7 @@ isc_hp_retire(isc_hp_t *hp, uintptr_t ptr) {
                uintptr_t obj = hp->rl[tid()]->list[iret];
                bool can_delete = true;
                for (int itid = 0;
-                    itid < HP_MAX_THREADS && can_delete;
+                    itid < isc__hp_max_threads && can_delete;
                     itid++)
                {
                        for (int ihp = hp->max_hps-1; ihp >= 0; ihp--) {
index 678c5f8b28d2ae27b5479bceeda1cf4038b947cc..dba0a64836289af6309b4f0b2761203dbeb7ab00 100644 (file)
 typedef void
 (isc_hp_deletefunc_t)(void *);
 
+void
+isc_hp_init(int max_threads);
+/*%<
+ * Initialize hazard pointer constants - isc__hp_max_threads. If more threads
+ * will try to access hp it will assert.
+ */
+
 isc_hp_t *
 isc_hp_new(isc_mem_t *mctx, size_t max_hps, isc_hp_deletefunc_t *deletefunc);
 /*%<
index 5d5b939ea9fa25e397d082312dc65f0377601f1f..07074ec6b3afb53d769f9ce921ae19f513ea98a0 100644 (file)
@@ -248,6 +248,7 @@ isc_hex_tobuffer
 isc_hex_totext
 isc_hp_clear
 isc_hp_destroy
+isc_hp_init
 isc_hp_protect
 isc_hp_protect_ptr
 isc_hp_protect_release