]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Use isc_mem_get_aligned() for isc_queue and cleanup max_threads
authorOndřej Surý <ondrej@sury.org>
Tue, 14 Dec 2021 21:16:39 +0000 (22:16 +0100)
committerOndřej Surý <ondrej@isc.org>
Wed, 5 Jan 2022 16:10:58 +0000 (17:10 +0100)
The isc_queue_new() was using dirty tricks to allocate the head and tail
members of the struct aligned to the cacheline.  We can now use
isc_mem_get_aligned() to allocate the structure to the cacheline
directly.

Use ISC_OS_CACHELINE_SIZE (64) instead of arbitrary ALIGNMENT (128), one
cacheline size is enough to prevent false sharing.

Cleanup the unused max_threads variable - there was actually no limit on
the maximum number of threads.  This was changed a while ago.

lib/isc/include/isc/queue.h
lib/isc/netmgr/netmgr.c
lib/isc/queue.c

index a48af88881590a9b7c8e0df76b4571c79c16d3b4..1e2821c87852c5465d088354e508390c8de86a47 100644 (file)
@@ -15,7 +15,7 @@
 typedef struct isc_queue isc_queue_t;
 
 isc_queue_t *
-isc_queue_new(isc_mem_t *mctx, int max_threads);
+isc_queue_new(isc_mem_t *mctx);
 /*%<
  * Create a new fetch-and-add array queue.
  *
index 51045521a1d22a03fda01fdbc7e2dcead0d2da3a..e5e9a120bc8fac57dc9fdadad16a2453186b9503 100644 (file)
@@ -312,7 +312,7 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
                isc_condition_init(&worker->cond_prio);
 
                for (size_t type = 0; type < NETIEVENT_MAX; type++) {
-                       worker->ievents[type] = isc_queue_new(mgr->mctx, 128);
+                       worker->ievents[type] = isc_queue_new(mgr->mctx);
                        atomic_init(&worker->nievents[type], 0);
                }
 
index d16c8e69ae6a8ba5009e461624862e0e870a1e14..590bc92a535d0ed2d2776c44de14f96f3abc2338 100644 (file)
 #include <isc/atomic.h>
 #include <isc/hp.h>
 #include <isc/mem.h>
+#include <isc/os.h>
 #include <isc/queue.h>
 #include <isc/string.h>
 
 #define BUFFER_SIZE 1024
 
-#define MAX_THREADS 128
-
-#define ALIGNMENT 128
-
 static uintptr_t nulluintptr = (uintptr_t)NULL;
 
 typedef struct node {
@@ -39,13 +36,11 @@ typedef struct node {
 #define HP_HEAD 0
 
 struct isc_queue {
-       alignas(ALIGNMENT) atomic_uintptr_t head;
-       alignas(ALIGNMENT) atomic_uintptr_t tail;
+       alignas(ISC_OS_CACHELINE_SIZE) atomic_uintptr_t head;
+       alignas(ISC_OS_CACHELINE_SIZE) atomic_uintptr_t tail;
        isc_mem_t *mctx;
-       int max_threads;
        int taken;
        isc_hp_t *hp;
-       void *alloced_ptr;
 };
 
 static node_t *
@@ -93,27 +88,14 @@ queue_cas_head(isc_queue_t *queue, node_t *cmp, const node_t *val) {
 }
 
 isc_queue_t *
-isc_queue_new(isc_mem_t *mctx, int max_threads) {
+isc_queue_new(isc_mem_t *mctx) {
        isc_queue_t *queue = NULL;
        node_t *sentinel = NULL;
-       void *qbuf = NULL;
-       uintptr_t qptr;
-
-       /*
-        * A trick to allocate an aligned isc_queue_t structure
-        */
-       qbuf = isc_mem_get(mctx, sizeof(*queue) + ALIGNMENT);
-       qptr = (uintptr_t)qbuf;
-       queue = (isc_queue_t *)(qptr + (ALIGNMENT - (qptr % ALIGNMENT)));
-
-       if (max_threads == 0) {
-               max_threads = MAX_THREADS;
-       }
 
-       *queue = (isc_queue_t){
-               .max_threads = max_threads,
-               .alloced_ptr = qbuf,
-       };
+       queue = isc_mem_get_aligned(mctx, sizeof(*queue),
+                                   ISC_OS_CACHELINE_SIZE);
+
+       *queue = (isc_queue_t){ 0 };
 
        isc_mem_attach(mctx, &queue->mctx);
 
@@ -137,7 +119,7 @@ isc_queue_enqueue(isc_queue_t *queue, uintptr_t item) {
                uint_fast32_t idx;
                uintptr_t n = nulluintptr;
 
-               lt = (node_t *)isc_hp_protect(queue->hp, 0, &queue->tail);
+               lt = (node_t *)isc_hp_protect(queue->hp, HP_TAIL, &queue->tail);
                idx = atomic_fetch_add(&lt->enqidx, 1);
                if (idx > BUFFER_SIZE - 1) {
                        node_t *lnext = NULL;
@@ -178,7 +160,7 @@ isc_queue_dequeue(isc_queue_t *queue) {
                uint_fast32_t idx;
                uintptr_t item;
 
-               lh = (node_t *)isc_hp_protect(queue->hp, 0, &queue->head);
+               lh = (node_t *)isc_hp_protect(queue->hp, HP_HEAD, &queue->head);
                if (atomic_load(&lh->deqidx) >= atomic_load(&lh->enqidx) &&
                    atomic_load(&lh->next) == nulluintptr)
                {
@@ -215,7 +197,6 @@ isc_queue_dequeue(isc_queue_t *queue) {
 void
 isc_queue_destroy(isc_queue_t *queue) {
        node_t *last = NULL;
-       void *alloced = NULL;
 
        REQUIRE(queue != NULL);
 
@@ -227,6 +208,6 @@ isc_queue_destroy(isc_queue_t *queue) {
        node_destroy(last);
        isc_hp_destroy(queue->hp);
 
-       alloced = queue->alloced_ptr;
-       isc_mem_putanddetach(&queue->mctx, alloced, sizeof(*queue) + ALIGNMENT);
+       isc_mem_putanddetach_aligned(&queue->mctx, queue, sizeof(*queue),
+                                    ISC_OS_CACHELINE_SIZE);
 }