mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-26 11:22:52 -04:00
Fix non-atomic read-modify-write on entry->srtt in adjustsrtt()
The SRTT update loaded the old value, computed a new one, and stored it
back as separate operations. Two concurrent callers could each read the
same old value and one update would be silently lost.
Use a CAS loop for the read-modify-write on entry->srtt. For the aging
path, also CAS on entry->lastage to prevent multiple threads from aging
the same entry in the same second.
(cherry picked from commit 4d15494b94)
This commit is contained in:
parent
be7b811fff
commit
fb8a9e73cc
1 changed files with 25 additions and 12 deletions
|
|
@ -3029,22 +3029,35 @@ static void
|
|||
adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor,
|
||||
isc_stdtime_t now) {
|
||||
unsigned int new_srtt;
|
||||
unsigned int old_srtt;
|
||||
|
||||
if (factor == DNS_ADB_RTTADJAGE) {
|
||||
if (atomic_load(&addr->entry->lastage) != now) {
|
||||
new_srtt = (uint64_t)atomic_load(&addr->entry->srtt) *
|
||||
98 / 100;
|
||||
atomic_store(&addr->entry->lastage, now);
|
||||
atomic_store(&addr->entry->srtt, new_srtt);
|
||||
addr->srtt = new_srtt;
|
||||
isc_stdtime_t lastage =
|
||||
atomic_load_acquire(&addr->entry->lastage);
|
||||
|
||||
/* prevent double aging */
|
||||
if (lastage == now ||
|
||||
!atomic_compare_exchange_strong_acq_rel(
|
||||
&addr->entry->lastage, &lastage, now))
|
||||
{
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
new_srtt = ((uint64_t)atomic_load(&addr->entry->srtt) / 10 *
|
||||
factor) +
|
||||
((uint64_t)rtt / 10 * (10 - factor));
|
||||
atomic_store(&addr->entry->srtt, new_srtt);
|
||||
addr->srtt = new_srtt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Correct CAS aging...
|
||||
*/
|
||||
old_srtt = atomic_load_acquire(&addr->entry->srtt);
|
||||
do {
|
||||
if (factor == DNS_ADB_RTTADJAGE) {
|
||||
new_srtt = (uint64_t)old_srtt * 98 / 100;
|
||||
} else {
|
||||
new_srtt = ((uint64_t)old_srtt / 10 * factor) +
|
||||
((uint64_t)rtt / 10 * (10 - factor));
|
||||
}
|
||||
} while (!atomic_compare_exchange_weak_acq_rel(&addr->entry->srtt,
|
||||
&old_srtt, new_srtt));
|
||||
addr->srtt = new_srtt;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Reference in a new issue