]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
ensure isc_queue_t is aligned to double-cacheline size
authorWitold Kręcicki <wpk@culm.net>
Fri, 15 Nov 2019 09:47:08 +0000 (10:47 +0100)
committerEvan Hunt <each@isc.org>
Mon, 18 Nov 2019 02:59:40 +0000 (18:59 -0800)
lib/isc/queue.c

index 172907990674b16b2f79fbc20ab0ac4436beba07..5072adaaa58634ff710202ed1200822324b1631c 100644 (file)
@@ -22,6 +22,8 @@
 
 #define MAX_THREADS 128
 
+#define ALIGNMENT 128
+
 static uintptr_t nulluintptr = (uintptr_t)NULL;
 
 typedef struct node {
@@ -37,12 +39,13 @@ typedef struct node {
 #define HP_HEAD 0
 
 struct isc_queue {
-       alignas(128) atomic_uintptr_t   head;
-       alignas(128) atomic_uintptr_t   tail;
+       alignas(ALIGNMENT) atomic_uintptr_t     head;
+       alignas(ALIGNMENT) atomic_uintptr_t     tail;
        isc_mem_t                       *mctx;
        int                             max_threads;
        int                             taken;
        isc_hp_t                        *hp;
+       void*                           alloced_ptr;
 };
 
 static node_t *
@@ -96,8 +99,17 @@ 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_t *queue = isc_mem_get(mctx, sizeof(*queue));
-       node_t *sentinel = node_new(mctx, nulluintptr);
+       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;
@@ -105,13 +117,16 @@ isc_queue_new(isc_mem_t *mctx, int max_threads) {
 
        *queue = (isc_queue_t){
                .max_threads = max_threads,
+               .alloced_ptr = qbuf,
        };
 
        isc_mem_attach(mctx, &queue->mctx);
 
        queue->hp = isc_hp_new(mctx, 1, node_destroy);
 
+       sentinel = node_new(mctx, nulluintptr);
        atomic_init(&sentinel->enqidx, 0);
+
        atomic_init(&queue->head, (uintptr_t)sentinel);
        atomic_init(&queue->tail, (uintptr_t)sentinel);
 
@@ -205,6 +220,7 @@ 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);
 
@@ -215,5 +231,8 @@ isc_queue_destroy(isc_queue_t *queue) {
        last = (node_t *)atomic_load_relaxed(&queue->head);
        node_destroy(last);
        isc_hp_destroy(queue->hp);
-       isc_mem_putanddetach(&queue->mctx, queue, sizeof(*queue));
+
+       alloced = queue->alloced_ptr;
+       isc_mem_putanddetach(&queue->mctx, alloced,
+                            sizeof(*queue) + ALIGNMENT);
 }