From 063a881a6c6c6bd542b0c24e1fb2882f5b7b264e Mon Sep 17 00:00:00 2001
From: Mark Andrews <marka@isc.org>
Date: Thu, 27 Aug 2020 15:12:10 +1000
Subject: [PATCH] Use atomics to update counters.

WARNING: ThreadSanitizer: data race
  Write of size 4 at 0x000000000001 by thread T1:
    #0 dns_acache_countquerymiss lib/dns/acache.c:1184:22
    #1 rdataset_getadditional lib/dns/rbtdb.c:9875:3
    #2 dns_rdataset_getadditional lib/dns/rdataset.c:711:11
    #3 query_addadditional2 bin/named/query.c:1967:11
    #4 additionaldata_ns lib/dns/./rdata/generic/ns_2.c:198:10
    #5 dns_rdata_additionaldata lib/dns/rdata.c:1246:2
    #6 dns_rdataset_additionaldata lib/dns/rdataset.c:629:12
    #7 query_addrdataset bin/named/query.c:2411:8
    #8 query_addrrset bin/named/query.c:2802:2
    #9 query_find bin/named/query.c:9135:4
    #10 query_resume bin/named/query.c:4164:12
    #11 dispatch lib/isc/task.c:1157:7
    #12 run lib/isc/task.c:1331:2

  Previous write of size 4 at 0x000000000001 by thread T2:
    #0 dns_acache_countquerymiss lib/dns/acache.c:1184:22
    #1 rdataset_getadditional lib/dns/rbtdb.c:9875:3
    #2 dns_rdataset_getadditional lib/dns/rdataset.c:711:11
    #3 query_addadditional2 bin/named/query.c:1967:11
    #4 additionaldata_ns lib/dns/./rdata/generic/ns_2.c:198:10
    #5 dns_rdata_additionaldata lib/dns/rdata.c:1246:2
    #6 dns_rdataset_additionaldata lib/dns/rdataset.c:629:12
    #7 query_addrdataset bin/named/query.c:2411:8
    #8 query_addrrset bin/named/query.c:2802:2
    #9 query_find bin/named/query.c:9135:4
    #10 query_resume bin/named/query.c:4164:12
    #11 dispatch lib/isc/task.c:1157:7
    #12 run lib/isc/task.c:1331:2
Conflict: NA
Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/063a881a6c6c6bd542b0c24e1fb2882f5b7b264e
---
 lib/dns/acache.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/lib/dns/acache.c b/lib/dns/acache.c
index fc6973f4cc..14ba672135 100644
--- a/lib/dns/acache.c
+++ b/lib/dns/acache.c
@@ -174,9 +174,24 @@ struct acache_cleaner {
 };
 
 struct dns_acachestats {
+#ifdef ACACHE_HAVESTDATOMIC
+	_Atomic(unsigned int)		hits;
+	_Atomic(unsigned int)		queries;
+	_Atomic(unsigned int)		misses;
+#define ACACHE_INC(x)	atomic_fetch_add(&(x), 1)
+#define ACACHE_LOAD(x)  atomic_load(&(x))
+#else
 	unsigned int			hits;
 	unsigned int			queries;
 	unsigned int			misses;
+#if defined(ISC_PLATFORM_HAVEXADD)
+#define ACACHE_INC(x) isc_atomic_xadd((int32_t*)&(x), 1)
+#define ACACHE_LOAD(x) isc_atomic_xadd((int32_t*)&(x), 0)
+#else
+#define ACACHE_INC(x) ((x)++)
+#define ACACHE_LOAD(x) (x)
+#endif
+#endif
 	unsigned int			adds;
 	unsigned int			deleted;
 	unsigned int			cleaned;
@@ -716,8 +731,9 @@ end_cleaning(acache_cleaner_t *cleaner, isc_event_t *event) {
 		      "cleaned=%d cleaner_runs=%d overmem=%d "
 		      "overmem_nocreates=%d nomem=%d",
 		      acache,
-		      acache->stats.hits, acache->stats.misses,
-		      acache->stats.queries,
+		      ACACHE_LOAD(acache->stats.hits),
+		      ACACHE_LOAD(acache->stats.misses),
+		      ACACHE_LOAD(acache->stats.queries),
 		      acache->stats.adds, acache->stats.deleted,
 		      acache->stats.cleaned, acache->stats.cleaner_runs,
 		      acache->stats.overmem, acache->stats.overmem_nocreates,
@@ -1181,8 +1197,8 @@ dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp) {
 
 void
 dns_acache_countquerymiss(dns_acache_t *acache) {
-	acache->stats.misses++; 	/* XXXSK danger: unlocked! */
-	acache->stats.queries++;	/* XXXSK danger: unlocked! */
+	ACACHE_INC(acache->stats.misses);
+	ACACHE_INC(acache->stats.queries);
 }
 
 void
@@ -1529,8 +1545,8 @@ dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep,
 		}
 	}
 
-	entry->acache->stats.hits++; /* XXXMLG danger: unlocked! */
-	entry->acache->stats.queries++;
+	ACACHE_INC(entry->acache->stats.hits);
+	ACACHE_INC(entry->acache->stats.queries);
 
 	ACACHE_UNLOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);
 
-- 
2.23.0

