]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add isc_queue implementation on top of cds_wfcq
authorOndřej Surý <ondrej@isc.org>
Mon, 25 Mar 2024 11:17:42 +0000 (12:17 +0100)
committerOndřej Surý <ondrej@isc.org>
Wed, 5 Jun 2024 07:19:56 +0000 (09:19 +0200)
Add an isc_queue implementation that hides the gory details of cds_wfcq
into more neat API.  The same caveats as with cds_wfcq.

TODO: Add documentation to the API.

lib/isc/Makefile.am
lib/isc/include/isc/queue.h [new file with mode: 0644]

index f6343136efb2f8b479b6733cdfd16b21ce237eb7..8a84c407e2c7850a5732e429f1f84146edb0389a 100644 (file)
@@ -64,6 +64,7 @@ libisc_la_HEADERS =                   \
        include/isc/pause.h             \
        include/isc/portset.h           \
        include/isc/proxy2.h            \
+       include/isc/queue.h             \
        include/isc/quota.h             \
        include/isc/radix.h             \
        include/isc/random.h            \
diff --git a/lib/isc/include/isc/queue.h b/lib/isc/include/isc/queue.h
new file mode 100644 (file)
index 0000000..743d3c6
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <isc/os.h>
+#include <isc/urcu.h>
+
+STATIC_ASSERT(sizeof(struct __cds_wfcq_head) <= ISC_OS_CACHELINE_SIZE,
+             "size of struct __cds_wfcq_head must be smaller than "
+             "ISC_OS_CACHELINE_SIZE");
+
+typedef struct isc_queue {
+       struct __cds_wfcq_head head;
+       uint8_t                __padding[ISC_OS_CACHELINE_SIZE -
+                                sizeof(struct __cds_wfcq_head)];
+       struct cds_wfcq_tail   tail;
+} isc_queue_t;
+
+typedef struct cds_wfcq_node isc_queue_node_t;
+
+static inline void
+isc_queue_node_init(isc_queue_node_t *node) {
+       cds_wfcq_node_init(node);
+}
+
+static inline void
+isc_queue_init(isc_queue_t *queue) {
+       __cds_wfcq_init(&(queue)->head, &(queue)->tail);
+}
+
+static inline void
+isc_queue_destroy(isc_queue_t *queue) {
+       UNUSED(queue);
+}
+
+static inline bool
+isc_queue_empty(isc_queue_t *queue) {
+       return (cds_wfcq_empty(&(queue)->head, &(queue)->tail));
+}
+
+static inline bool
+isc_queue_enqueue(isc_queue_t *queue, isc_queue_node_t *node) {
+       return (cds_wfcq_enqueue(&(queue)->head, &(queue)->tail, node));
+}
+
+#define isc_queue_enqueue_entry(queue, entry, member) \
+       cds_wfcq_enqueue(&(queue)->head, &(queue)->tail, &((entry)->member))
+
+static inline isc_queue_node_t *
+isc_queue_dequeue(isc_queue_t *queue) {
+       return (__cds_wfcq_dequeue_nonblocking(&(queue)->head, &(queue)->tail));
+}
+
+#define isc_queue_entry(ptr, type, member) \
+       caa_container_of_check_null(ptr, type, member)
+
+#define isc_queue_dequeue_entry(queue, type, member) \
+       isc_queue_entry(isc_queue_dequeue(queue), type, member)
+
+static inline bool
+isc_queue_splice(isc_queue_t *dest, isc_queue_t *src) {
+       enum cds_wfcq_ret ret = __cds_wfcq_splice_blocking(
+               &dest->head, &dest->tail, &src->head, &src->tail);
+       INSIST(ret != CDS_WFCQ_RET_WOULDBLOCK &&
+              ret != CDS_WFCQ_RET_DEST_NON_EMPTY);
+
+       return (ret != CDS_WFCQ_RET_SRC_EMPTY);
+}
+
+#define isc_queue_first_entry(queue, type, member)                         \
+       isc_queue_entry(                                                   \
+               __cds_wfcq_first_blocking(&(queue)->head, &(queue)->tail), \
+               type, member)
+
+#define isc_queue_next_entry(queue, node, type, member)                 \
+       isc_queue_entry(__cds_wfcq_next_blocking(&(queue)->head,        \
+                                                &(queue)->tail, node), \
+                       type, member)
+
+#define isc_queue_for_each_entry(queue, pos, member)                       \
+       for (pos = isc_queue_first_entry(queue, __typeof__(*pos), member); \
+            pos != NULL;                                                  \
+            pos = isc_queue_next_entry(queue, &(pos)->member,             \
+                                       __typeof__(*pos), member))
+
+#define isc_queue_for_each_entry_safe(queue, pos, next, member)            \
+       for (pos = isc_queue_first_entry(queue, __typeof__(*pos), member), \
+           next = (pos ? isc_queue_next_entry(queue, &(pos)->member,      \
+                                              __typeof__(*pos), member)   \
+                       : NULL);                                           \
+            pos != NULL; pos = next,                                      \
+           next = (pos ? isc_queue_next_entry(queue, &(pos)->member,      \
+                                              __typeof__(*pos), member)   \
+                       : NULL))