dns_rdatatype_t type;
};
-#define DNS_SLABTOP_FOREACH(elt, first) \
- for (dns_slabtop_t *elt = first, \
- *elt##_next = (elt != NULL) ? elt->next : NULL; \
- elt != NULL; \
- elt = elt##_next, elt##_next = (elt != NULL) ? elt->next : NULL)
+#define DNS_SLABTOP_FOREACH(pos, head) \
+ dns_slabtop_t *pos = NULL, *pos##_next = NULL; \
+ cds_list_for_each_entry_safe(pos, pos##_next, head, types_link)
+
+#define DNS_SLABTOP_FOREACH_FROM(pos, head, first) \
+ dns_slabtop_t *pos = first, *pos##_next = NULL; \
+ cds_list_for_each_entry_safe_from(pos, pos##_next, head, types_link)
typedef struct dns_slabtop dns_slabtop_t;
struct dns_slabtop {
- dns_slabtop_t *next;
+ struct cds_list_head types_link;
+
dns_slabheader_t *header;
dns_typepair_t typepair;
isc_refcount_t references;
isc_refcount_t erefs;
- dns_slabtop_t *data;
+ struct cds_list_head types_list;
+ struct cds_list_head *data;
/*%
* NOTE: The 'dirty' flag is protected by the node lock, so
static void
clean_cache_node(qpcache_t *qpdb, qpcnode_t *node) {
- dns_slabtop_t *top_prev = NULL;
-
/*
* Caller must be holding the node lock.
*/
* If current slabtop is empty, we can clean it up.
*/
if (top->header == NULL) {
- if (top_prev != NULL) {
- top_prev->next = top->next;
- } else {
- node->data = top->next;
- }
+ cds_list_del(&top->types_link);
if (ISC_LINK_LINKED(top, link)) {
ISC_SIEVE_UNLINK(
link);
}
dns_slabtop_destroy(((dns_db_t *)qpdb)->mctx, &top);
- } else {
- top_prev = top;
}
}
}
/* Handle easy and typical case first. */
- if (!node->dirty && node->data != NULL) {
+ if (!node->dirty && !cds_list_empty(node->data)) {
goto unref;
}
clean_cache_node(qpdb, node);
}
- if (node->data != NULL) {
+ if (!cds_list_empty(node->data)) {
goto unref;
}
new_qpcnode(qpcache_t *qpdb, const dns_name_t *name, dns_namespace_t nspace) {
qpcnode_t *newdata = isc_mem_get(qpdb->common.mctx, sizeof(*newdata));
*newdata = (qpcnode_t){
+ .types_list = CDS_LIST_HEAD_INIT(newdata->types_list),
+ .data = &newdata->types_list,
.methods = &qpcnode_methods,
.qpdb = qpdb,
.name = DNS_NAME_INITEMPTY,
if (prio_header(newtop)) {
/* This is a priority type, prepend it */
- newtop->next = qpnode->data;
- qpnode->data = newtop;
+ cds_list_add(&newtop->types_link, qpnode->data);
} else if (priotop != NULL) {
/* Append after the priority headers */
- newtop->next = priotop->next;
- priotop->next = newtop;
+ cds_list_add(&newtop->types_link, &priotop->types_link);
} else {
/* There were no priority headers */
- newtop->next = qpnode->data;
- qpnode->data = newtop;
+ cds_list_add(&newtop->types_link, qpnode->data);
}
if (overmaxtype(qpdb, ntypes)) {
qpcnode_t *qpnode = (qpcnode_t *)iterator->common.node;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = &qpdb->buckets[qpnode->locknum].lock;
- dns_slabtop_t *next = NULL;
+ dns_slabtop_t *from = NULL;
if (iterator->current == NULL) {
return ISC_R_NOMORE;
}
- next = iterator->current->next;
- iterator->current = NULL;
NODE_RDLOCK(nlock, &nlocktype);
- DNS_SLABTOP_FOREACH(top, next) {
- dns_slabheader_t *header = first_existing_header(top);
+ from = cds_list_entry(iterator->current->types_link.next, dns_slabtop_t,
+ types_link);
+ iterator->current = NULL;
- if (EXPIREDOK(iterator) ||
- (header != NULL && iterator_active(qpdb, iterator, header)))
- {
- iterator->current = top;
- break;
+ if (from != NULL) {
+ DNS_SLABTOP_FOREACH_FROM(top, qpnode->data, from) {
+ dns_slabheader_t *header = first_existing_header(top);
+
+ if (EXPIREDOK(iterator) ||
+ (header != NULL &&
+ iterator_active(qpdb, iterator, header)))
+ {
+ iterator->current = top;
+ break;
+ }
}
}
atomic_bool wild;
atomic_bool delegating;
atomic_bool dirty;
- dns_slabtop_t *data;
+
+ struct cds_list_head types_list;
+ struct cds_list_head *data;
};
struct qpzonedb {
new_qpznode(qpzonedb_t *qpdb, const dns_name_t *name, dns_namespace_t nspace) {
qpznode_t *newdata = isc_mem_get(qpdb->common.mctx, sizeof(*newdata));
*newdata = (qpznode_t){
+ .types_list = CDS_LIST_HEAD_INIT(newdata->types_list),
+ .data = &newdata->types_list,
.methods = &qpznode_methods,
.name = DNS_NAME_INITEMPTY,
.nspace = nspace,
static void
clean_zone_node(qpznode_t *node, uint32_t least_serial) {
- dns_slabtop_t *top_prev = NULL;
bool still_dirty = false;
/*
check_top_header(top);
if (top->header == NULL) {
- if (top_prev != NULL) {
- top_prev->next = top->next;
- } else {
- node->data = top->next;
- }
+ cds_list_del(&top->types_link);
dns_slabtop_destroy(node->mctx, &top);
} else {
/*
*/
still_dirty = clean_multiple_versions(top,
least_serial);
-
- top_prev = top;
}
}
if (!still_dirty) {
}
/* Handle easy and typical case first. */
- if (!node->dirty && node->data != NULL) {
+ if (!node->dirty && !cds_list_empty(node->data)) {
goto unref;
}
if (prio_type(newheader->typepair)) {
/* This is a priority type, prepend it */
- newtop->next = node->data;
- node->data = newtop;
+ cds_list_add(&newtop->types_link, node->data);
} else if (priotop != NULL) {
/* Append after the priority headers */
- newtop->next = priotop->next;
- priotop->next = newtop;
+ cds_list_add(&newtop->types_link,
+ &priotop->types_link);
} else {
/* There were no priority headers */
- newtop->next = node->data;
- node->data = newtop;
+ cds_list_add(&newtop->types_link, node->data);
}
}
}
qpz_version_t *version = (qpz_version_t *)qrditer->common.version;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
isc_rwlock_t *nlock = qpzone_get_lock(node);
- dns_slabtop_t *next = NULL;
+ dns_slabtop_t *from = NULL;
if (qrditer->currenttop == NULL) {
return ISC_R_NOMORE;
}
- next = qrditer->currenttop->next;
- qrditer->currenttop = NULL;
- qrditer->current = NULL;
NODE_RDLOCK(nlock, &nlocktype);
+ from = cds_list_entry(qrditer->currenttop->types_link.next,
+ dns_slabtop_t, types_link);
+ qrditer->currenttop = NULL;
+ qrditer->current = NULL;
+
/*
* Find the start of the header chain for the next type.
*/
- DNS_SLABTOP_FOREACH(top, next) {
- qrditer->current = first_existing_header(top, version->serial);
- if (qrditer->current != NULL) {
- qrditer->currenttop = top;
- break;
+ if (from != NULL) {
+ DNS_SLABTOP_FOREACH_FROM(top, node->data, from) {
+ qrditer->current =
+ first_existing_header(top, version->serial);
+ if (qrditer->current != NULL) {
+ qrditer->currenttop = top;
+ break;
+ }
}
}
dns_slabtop_new(isc_mem_t *mctx, dns_typepair_t typepair) {
dns_slabtop_t *top = isc_mem_get(mctx, sizeof(*top));
*top = (dns_slabtop_t){
+ .types_link = CDS_LIST_HEAD_INIT(top->types_link),
.typepair = typepair,
.link = ISC_LINK_INITIALIZER,
};
#include <urcu-pointer.h>
#include <urcu/compiler.h>
+#include <urcu/list.h>
#include <urcu/rculfhash.h>
#include <urcu/rculist.h>
#include <urcu/wfstack.h>