rbtdb_serial_t serial;
dns_ttl_t rdh_ttl;
rbtdb_rdatatype_t type;
- uint16_t attributes;
+ atomic_uint_least16_t attributes;
dns_trust_t trust;
struct noqname *noqname;
struct noqname *closest;
#undef IGNORE /* WIN32 winbase.h defines this. */
-#define EXISTS(header) (((header)->attributes & RDATASET_ATTR_NONEXISTENT) == 0)
-#define NONEXISTENT(header) \
- (((header)->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
-#define IGNORE(header) (((header)->attributes & RDATASET_ATTR_IGNORE) != 0)
-#define RETAIN(header) (((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
-#define NXDOMAIN(header) (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
-#define STALE(header) (((header)->attributes & RDATASET_ATTR_STALE) != 0)
-#define RESIGN(header) (((header)->attributes & RDATASET_ATTR_RESIGN) != 0)
-#define OPTOUT(header) (((header)->attributes & RDATASET_ATTR_OPTOUT) != 0)
-#define NEGATIVE(header) (((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0)
-#define PREFETCH(header) (((header)->attributes & RDATASET_ATTR_PREFETCH) != 0)
-#define CASESET(header) (((header)->attributes & RDATASET_ATTR_CASESET) != 0)
-#define ZEROTTL(header) (((header)->attributes & RDATASET_ATTR_ZEROTTL) != 0)
-#define CASEFULLYLOWER(header) \
- (((header)->attributes & RDATASET_ATTR_CASEFULLYLOWER) != 0)
-#define ANCIENT(header) (((header)->attributes & RDATASET_ATTR_ANCIENT) != 0)
+#define EXISTS(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_NONEXISTENT) == 0)
+#define NONEXISTENT(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_NONEXISTENT) != 0)
+#define IGNORE(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_IGNORE) != 0)
+#define RETAIN(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_RETAIN) != 0)
+#define NXDOMAIN(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_NXDOMAIN) != 0)
+#define STALE(header) \
+ ((atomic_load_acquire(&(header)->attributes) & RDATASET_ATTR_STALE) != \
+ 0)
+#define RESIGN(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_RESIGN) != 0)
+#define OPTOUT(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_OPTOUT) != 0)
+#define NEGATIVE(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_NEGATIVE) != 0)
+#define PREFETCH(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_PREFETCH) != 0)
+#define CASESET(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_CASESET) != 0)
+#define ZEROTTL(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_ZEROTTL) != 0)
+#define CASEFULLYLOWER(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_CASEFULLYLOWER) != 0)
+#define ANCIENT(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_ANCIENT) != 0)
+#define STATCOUNT(header) \
+ ((atomic_load_acquire(&(header)->attributes) & \
+ RDATASET_ATTR_STATCOUNT) != 0)
+
+#define RDATASET_ATTR_GET(header, attribute) \
+ (atomic_load_acquire(&(header)->attributes) & attribute)
+#define RDATASET_ATTR_SET(header, attribute) \
+ atomic_fetch_or_release(&(header)->attributes, attribute)
+#define RDATASET_ATTR_CLR(header, attribute) \
+ atomic_fetch_and_release(&(header)->attributes, ~(attribute))
#define ACTIVE(header, now) \
(((header)->rdh_ttl > (now)) || \
static bool
do_stats(rdatasetheader_t *header) {
- return (EXISTS(header) &&
- (header->attributes & RDATASET_ATTR_STATCOUNT) != 0);
+ return (EXISTS(header) && STATCOUNT(header));
}
static void
-update_rrsetstats(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
- bool increment) {
+update_rrsetstats(dns_rbtdb_t *rbtdb, const rbtdb_rdatatype_t htype,
+ const uint_least16_t hattributes, const bool increment) {
dns_rdatastatstype_t statattributes = 0;
dns_rdatastatstype_t base = 0;
dns_rdatastatstype_t type;
+ rdatasetheader_t *header = &(rdatasetheader_t){
+ .type = htype, .attributes = ATOMIC_VAR_INIT(hattributes)
+ };
if (!do_stats(header)) {
return;
h->is_mmapped = 0;
h->next_is_relative = 0;
h->node_is_relative = 0;
+ atomic_init(&h->attributes, 0);
+
+#ifndef ISC_MUTEX_ATOMICS
+ STATIC_ASSERT((sizeof(h->attributes) == 2),
+ "The .attributes field of rdatasetheader_t needs to be "
+ "16-bit int type exactly.");
+#endif /* !ISC_MUTEX_ATOMICS */
#if TRACE_HEADER
if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in) {
newh->node = (dns_rbtnode_t *)p;
}
if (CASESET(old)) {
- uint16_t attr;
-
+ uint_least16_t attr = RDATASET_ATTR_GET(
+ old,
+ (RDATASET_ATTR_CASESET | RDATASET_ATTR_CASEFULLYLOWER));
+ RDATASET_ATTR_SET(newh, attr);
memmove(newh->upper, old->upper, sizeof(old->upper));
- attr = old->attributes &
- (RDATASET_ATTR_CASESET | RDATASET_ATTR_CASEFULLYLOWER);
- newh->attributes |= attr;
}
}
unsigned int size;
int idx;
- update_rrsetstats(rbtdb, rdataset, false);
+ update_rrsetstats(rbtdb, rdataset->type,
+ atomic_load_acquire(&rdataset->attributes), false);
idx = rdataset->node->locknum;
if (ISC_LINK_LINKED(rdataset, link)) {
*/
for (header = node->data; header != NULL; header = header->next) {
if (header->serial == serial) {
- header->attributes |= RDATASET_ATTR_IGNORE;
+ RDATASET_ATTR_SET(header, RDATASET_ATTR_IGNORE);
make_dirty = true;
}
for (dcurrent = header->down; dcurrent != NULL;
dcurrent = dcurrent->down) {
if (dcurrent->serial == serial) {
- dcurrent->attributes |= RDATASET_ATTR_IGNORE;
+ RDATASET_ATTR_SET(dcurrent,
+ RDATASET_ATTR_IGNORE);
make_dirty = true;
}
}
static inline void
mark_header_ancient(dns_rbtdb_t *rbtdb, rdatasetheader_t *header) {
+ uint_least16_t attributes = atomic_load_acquire(&header->attributes);
+ uint_least16_t newattributes = 0;
+
/*
* If we are already ancient there is nothing to do.
*/
- if (ANCIENT(header)) {
- return;
- }
+ do {
+ if ((attributes & RDATASET_ATTR_ANCIENT) != 0) {
+ return;
+ }
+ newattributes = attributes | RDATASET_ATTR_ANCIENT;
+ } while (!atomic_compare_exchange_weak_acq_rel(
+ &header->attributes, &attributes, newattributes));
/*
* Decrement the stats counter for the appropriate RRtype.
* stale type counter, otherwise it decrements the active
* stats type counter.
*/
- update_rrsetstats(rbtdb, header, false);
-
- header->attributes |= RDATASET_ATTR_ANCIENT;
+ update_rrsetstats(rbtdb, header->type, attributes, false);
header->node->dirty = 1;
/* Increment the stats counter for the ancient RRtype. */
- update_rrsetstats(rbtdb, header, true);
+ update_rrsetstats(rbtdb, header->type, newattributes, true);
}
static inline void
mark_header_stale(dns_rbtdb_t *rbtdb, rdatasetheader_t *header) {
+ uint_least16_t attributes = atomic_load_acquire(&header->attributes);
+ uint_least16_t newattributes = 0;
+
/*
* If we are already stale there is nothing to do.
*/
- if (STALE(header)) {
- return;
- }
+ do {
+ if ((attributes & RDATASET_ATTR_STALE) != 0) {
+ return;
+ }
+ newattributes = attributes | RDATASET_ATTR_STALE;
+ } while (!atomic_compare_exchange_weak_acq_rel(
+ &header->attributes, &attributes, newattributes));
/* Decrement the stats counter for the appropriate RRtype.
* If the ANCIENT attribute is set (although it is very
* will decrement the ancient stale type counter, otherwise it
* decrements the active stats type counter.
*/
- update_rrsetstats(rbtdb, header, false);
- header->attributes |= RDATASET_ATTR_STALE;
-
- update_rrsetstats(rbtdb, header, true);
+ update_rrsetstats(rbtdb, header->type, attributes, false);
+ update_rrsetstats(rbtdb, header->type, newattributes, true);
}
static inline void
first = true;
fprintf(out, "\ttype %u", current->type);
do {
+ uint_least16_t attributes = atomic_load_acquire(
+ ¤t->attributes);
if (!first) {
fprintf(out, "\t");
}
first = false;
fprintf(out,
"\tserial = %lu, ttl = %u, "
- "trust = %u, attributes = %u, "
+ "trust = %u, attributes = %" PRIuLEAST16
+ ", "
"resign = %u\n",
(unsigned long)current->serial,
current->rdh_ttl, current->trust,
- current->attributes,
+ attributes,
(current->resign << 1) |
current->resign_lsb);
current = current->down;
set_ttl(rbtdb, newheader, rdataset->ttl + now);
newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
rdataset->covers);
- newheader->attributes = 0;
+ atomic_init(&newheader->attributes, 0);
if (rdataset->ttl == 0U) {
- newheader->attributes |= RDATASET_ATTR_ZEROTTL;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_ZEROTTL);
}
newheader->noqname = NULL;
newheader->closest = NULL;
now = 0;
if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
- newheader->attributes |= RDATASET_ATTR_RESIGN;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_RESIGN);
newheader->resign = (isc_stdtime_t)(
dns_time64_from32(rdataset->resign) >> 1);
newheader->resign_lsb = rdataset->resign & 0x1;
newheader->resign = 0;
newheader->resign_lsb = 0;
if ((rdataset->attributes & DNS_RDATASETATTR_PREFETCH) != 0) {
- newheader->attributes |= RDATASET_ATTR_PREFETCH;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_PREFETCH);
}
if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) {
- newheader->attributes |= RDATASET_ATTR_NEGATIVE;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_NEGATIVE);
}
if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) {
- newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_NXDOMAIN);
}
if ((rdataset->attributes & DNS_RDATASETATTR_OPTOUT) != 0) {
- newheader->attributes |= RDATASET_ATTR_OPTOUT;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_OPTOUT);
}
if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
result = addnoqname(rbtdb, newheader, rdataset);
isc_rwlocktype_write);
if (rbtdb->rrsetstats != NULL) {
- newheader->attributes |= RDATASET_ATTR_STATCOUNT;
- update_rrsetstats(rbtdb, newheader, true);
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_STATCOUNT);
+ update_rrsetstats(rbtdb, newheader->type,
+ atomic_load_acquire(&newheader->attributes),
+ true);
}
if (IS_CACHE(rbtdb)) {
set_ttl(rbtdb, newheader, rdataset->ttl);
newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
rdataset->covers);
- newheader->attributes = 0;
+ atomic_init(&newheader->attributes, 0);
newheader->serial = rbtversion->serial;
newheader->trust = 0;
newheader->noqname = NULL;
newheader->last_used = 0;
newheader->node = rbtnode;
if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
- newheader->attributes |= RDATASET_ATTR_RESIGN;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_RESIGN);
newheader->resign = (isc_stdtime_t)(
dns_time64_from32(rdataset->resign) >> 1);
newheader->resign_lsb = rdataset->resign & 0x1;
init_rdataset(rbtdb, newheader);
update_newheader(newheader, header);
if (RESIGN(header)) {
- newheader->attributes |= RDATASET_ATTR_RESIGN;
+ RDATASET_ATTR_SET(newheader,
+ RDATASET_ATTR_RESIGN);
newheader->resign = header->resign;
newheader->resign_lsb = header->resign_lsb;
result = resign_insert(rbtdb, rbtnode->locknum,
init_rdataset(rbtdb, newheader);
set_ttl(rbtdb, newheader, 0);
newheader->type = topheader->type;
- newheader->attributes = RDATASET_ATTR_NONEXISTENT;
+ atomic_init(&newheader->attributes,
+ RDATASET_ATTR_NONEXISTENT);
newheader->trust = 0;
newheader->serial = rbtversion->serial;
newheader->noqname = NULL;
init_rdataset(rbtdb, newheader);
set_ttl(rbtdb, newheader, 0);
newheader->type = RBTDB_RDATATYPE_VALUE(type, covers);
- newheader->attributes = RDATASET_ATTR_NONEXISTENT;
+ atomic_init(&newheader->attributes, RDATASET_ATTR_NONEXISTENT);
newheader->trust = 0;
newheader->noqname = NULL;
newheader->closest = NULL;
* check */
newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
rdataset->covers);
- newheader->attributes = 0;
+ atomic_init(&newheader->attributes, 0);
newheader->trust = rdataset->trust;
newheader->serial = 1;
newheader->noqname = NULL;
setownercase(newheader, name);
if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
- newheader->attributes |= RDATASET_ATTR_RESIGN;
+ RDATASET_ATTR_SET(newheader, RDATASET_ATTR_RESIGN);
newheader->resign = (isc_stdtime_t)(
dns_time64_from32(rdataset->resign) >> 1);
newheader->resign_lsb = rdataset->resign & 0x1;
header->is_mmapped = 1;
header->node = rbtnode;
header->node_is_relative = 0;
+#ifdef ISC_MUTEX_ATOMICS
+ atomic_init(&header->attributes, header->attributes.v);
+#endif
if (RESIGN(header) &&
(header->resign != 0 || header->resign_lsb != 0)) {
header->heap_index);
}
} else if (resign != 0) {
- header->attributes |= RDATASET_ATTR_RESIGN;
+ RDATASET_ATTR_SET(header, RDATASET_ATTR_RESIGN);
result = resign_insert(rbtdb, header->node->locknum, header);
}
NODE_UNLOCK(&rbtdb->node_locks[header->node->locknum].lock,
header--;
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
- header->attributes &= ~RDATASET_ATTR_PREFETCH;
+ RDATASET_ATTR_CLR(header, RDATASET_ATTR_PREFETCH);
NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_write);
}
}
}
}
- header->attributes |= RDATASET_ATTR_CASESET;
+ RDATASET_ATTR_SET(header, RDATASET_ATTR_CASESET);
if (ISC_LIKELY(fully_lower)) {
- header->attributes |= RDATASET_ATTR_CASEFULLYLOWER;
+ RDATASET_ATTR_SET(header, RDATASET_ATTR_CASEFULLYLOWER);
}
}
rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
- const unsigned char *raw = rdataset->private3; /* RDATASLAB */
- const rdatasetheader_t *header;
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ rdatasetheader_t *header;
unsigned int i, j;
unsigned char bits;
unsigned char c, flip;
- header = (const struct rdatasetheader *)(raw - sizeof(*header));
+ header = (struct rdatasetheader *)(raw - sizeof(*header));
NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
isc_rwlocktype_read);
*/
static inline bool
need_headerupdate(rdatasetheader_t *header, isc_stdtime_t now) {
- if ((header->attributes &
- (RDATASET_ATTR_NONEXISTENT | RDATASET_ATTR_ANCIENT |
- RDATASET_ATTR_ZEROTTL)) != 0)
+ if (RDATASET_ATTR_GET(header, (RDATASET_ATTR_NONEXISTENT |
+ RDATASET_ATTR_ANCIENT |
+ RDATASET_ATTR_ZEROTTL)) != 0)
{
return (false);
}