mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-23 02:28:55 -04:00
Instead of having many node_lock_count * sizeof(<member>) arrays, pack all the members into a qpcache_bucket_t struct that is cacheline aligned and have a single array of those. Additionaly, make both the head and the tail of isc_queue_t padded, not just the head, to prevent false sharing of the lock-free structure with the lock that follows it.
105 lines
3.5 KiB
C
105 lines
3.5 KiB
C
/*
|
|
* 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_head[ISC_OS_CACHELINE_SIZE -
|
|
sizeof(struct __cds_wfcq_head)];
|
|
struct cds_wfcq_tail tail;
|
|
uint8_t __padding_tail[ISC_OS_CACHELINE_SIZE -
|
|
sizeof(struct __cds_wfcq_head)];
|
|
} 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))
|